mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
eth/gasprice: fix blob base fee ordering, simplify tests
This commit is contained in:
parent
9ec859b73c
commit
7305023635
3 changed files with 64 additions and 103 deletions
|
|
@ -53,7 +53,6 @@ type blockFees struct {
|
||||||
// set by the caller
|
// set by the caller
|
||||||
blockNumber uint64
|
blockNumber uint64
|
||||||
header *types.Header
|
header *types.Header
|
||||||
parentHeader *types.Header
|
|
||||||
block *types.Block // only set if reward percentiles are requested
|
block *types.Block // only set if reward percentiles are requested
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
// filled by processBlock
|
// filled by processBlock
|
||||||
|
|
@ -85,34 +84,31 @@ type txGasAndReward struct {
|
||||||
// the block field filled in, retrieves the block from the backend if not present yet and
|
// the block field filled in, retrieves the block from the backend if not present yet and
|
||||||
// fills in the rest of the fields.
|
// fills in the rest of the fields.
|
||||||
func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||||
chainconfig := oracle.backend.ChainConfig()
|
config := oracle.backend.ChainConfig()
|
||||||
|
|
||||||
|
// Fill in base fee and next base fee.
|
||||||
if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
|
if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
|
||||||
bf.results.baseFee = new(big.Int)
|
bf.results.baseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
|
if config.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
|
||||||
bf.results.nextBaseFee = eip1559.CalcBaseFee(chainconfig, bf.header)
|
bf.results.nextBaseFee = eip1559.CalcBaseFee(config, bf.header)
|
||||||
} else {
|
} else {
|
||||||
bf.results.nextBaseFee = new(big.Int)
|
bf.results.nextBaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
|
// Fill in blob base fee and next blob base fee.
|
||||||
bf.results.blobGasUsedRatio = 0.0
|
if excessBlobGas := bf.header.ExcessBlobGas; excessBlobGas != nil {
|
||||||
|
bf.results.blobBaseFee = eip4844.CalcBlobFee(*excessBlobGas)
|
||||||
|
bf.results.nextBlobBaseFee = eip4844.CalcBlobFee(eip4844.CalcExcessBlobGas(*excessBlobGas, *bf.header.BlobGasUsed))
|
||||||
|
} else {
|
||||||
bf.results.blobBaseFee = new(big.Int)
|
bf.results.blobBaseFee = new(big.Int)
|
||||||
|
bf.results.nextBlobBaseFee = new(big.Int)
|
||||||
getBlobBaseFee := func(h *types.Header) *big.Int {
|
|
||||||
if h != nil && chainconfig.IsCancun(h.Number, h.Time) {
|
|
||||||
if excessBlobGas := h.ExcessBlobGas; excessBlobGas != nil {
|
|
||||||
return eip4844.CalcBlobFee(*excessBlobGas)
|
|
||||||
}
|
}
|
||||||
}
|
// Compute gas used ratio for normal and blob gas.
|
||||||
return new(big.Int)
|
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
|
||||||
}
|
|
||||||
bf.results.blobBaseFee = getBlobBaseFee(bf.parentHeader)
|
|
||||||
bf.results.nextBlobBaseFee = getBlobBaseFee(bf.header)
|
|
||||||
if bf.header != nil && chainconfig.IsCancun(bf.header.Number, bf.header.Time) {
|
|
||||||
if blobGasUsed := bf.header.BlobGasUsed; blobGasUsed != nil {
|
if blobGasUsed := bf.header.BlobGasUsed; blobGasUsed != nil {
|
||||||
bf.results.blobGasUsedRatio = float64(*blobGasUsed) / params.MaxBlobGasPerBlock
|
bf.results.blobGasUsedRatio = float64(*blobGasUsed) / params.MaxBlobGasPerBlock
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if len(percentiles) == 0 {
|
if len(percentiles) == 0 {
|
||||||
// rewards were not requested, return null
|
// rewards were not requested, return null
|
||||||
return
|
return
|
||||||
|
|
@ -153,6 +149,15 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getBlobBaseFee is a helper function which computes and returns the blob base
|
||||||
|
// fee if excessBlobGas exists.
|
||||||
|
func getBlobBaseFee(h *types.Header) *big.Int {
|
||||||
|
if excessBlobGas := h.ExcessBlobGas; excessBlobGas != nil {
|
||||||
|
return eip4844.CalcBlobFee(*excessBlobGas)
|
||||||
|
}
|
||||||
|
return new(big.Int)
|
||||||
|
}
|
||||||
|
|
||||||
// resolveBlockRange resolves the specified block range to absolute block numbers while also
|
// resolveBlockRange resolves the specified block range to absolute block numbers while also
|
||||||
// enforcing backend specific limitations. The pending block and corresponding receipts are
|
// enforcing backend specific limitations. The pending block and corresponding receipts are
|
||||||
// also returned if requested and available.
|
// also returned if requested and available.
|
||||||
|
|
@ -290,7 +295,6 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
|
||||||
if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() {
|
if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() {
|
||||||
fees.block, fees.receipts = pendingBlock, pendingReceipts
|
fees.block, fees.receipts = pendingBlock, pendingReceipts
|
||||||
fees.header = fees.block.Header()
|
fees.header = fees.block.Header()
|
||||||
fees.parentHeader, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(pendingBlock.NumberU64()-1))
|
|
||||||
oracle.processBlock(fees, rewardPercentiles)
|
oracle.processBlock(fees, rewardPercentiles)
|
||||||
results <- fees
|
results <- fees
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -310,9 +314,6 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks uint64, unresolvedL
|
||||||
fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber))
|
fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber))
|
||||||
}
|
}
|
||||||
if fees.header != nil && fees.err == nil {
|
if fees.header != nil && fees.err == nil {
|
||||||
if blockNumber > 0 {
|
|
||||||
fees.parentHeader, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber-1))
|
|
||||||
}
|
|
||||||
oracle.processBlock(fees, rewardPercentiles)
|
oracle.processBlock(fees, rewardPercentiles)
|
||||||
if fees.err == nil {
|
if fees.err == nil {
|
||||||
oracle.historyCache.Add(cacheKey, fees.results)
|
oracle.historyCache.Add(cacheKey, fees.results)
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ func TestFeeHistory(t *testing.T) {
|
||||||
MaxHeaderHistory: c.maxHeader,
|
MaxHeaderHistory: c.maxHeader,
|
||||||
MaxBlockHistory: c.maxBlock,
|
MaxBlockHistory: c.maxBlock,
|
||||||
}
|
}
|
||||||
backend := newTestBackend(t, big.NewInt(16), c.pending, true)
|
backend := newTestBackend(t, big.NewInt(16), big.NewInt(28), c.pending)
|
||||||
oracle := NewOracle(backend, config)
|
oracle := NewOracle(backend, config)
|
||||||
|
|
||||||
first, reward, baseFee, ratio, blobBaseFee, blobRatio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
|
first, reward, baseFee, ratio, blobBaseFee, blobRatio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package gasprice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
|
@ -32,7 +31,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/beacon"
|
"github.com/ethereum/go-ethereum/consensus/beacon"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
@ -129,7 +127,10 @@ func (b *testBackend) teardown() {
|
||||||
|
|
||||||
// newTestBackend creates a test backend. OBS: don't forget to invoke tearDown
|
// newTestBackend creates a test backend. OBS: don't forget to invoke tearDown
|
||||||
// after use, otherwise the blockchain instance will mem-leak via goroutines.
|
// after use, otherwise the blockchain instance will mem-leak via goroutines.
|
||||||
func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool, addCancunBlocks bool) *testBackend {
|
func newTestBackend(t *testing.T, londonBlock *big.Int, cancunBlock *big.Int, pending bool) *testBackend {
|
||||||
|
if londonBlock != nil && cancunBlock != nil && londonBlock.Cmp(cancunBlock) == 1 {
|
||||||
|
panic("cannot define test backend with cancun before london")
|
||||||
|
}
|
||||||
var (
|
var (
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
addr = crypto.PubkeyToAddress(key.PublicKey)
|
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||||
|
|
@ -139,31 +140,28 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool, addCancunB
|
||||||
Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
|
Alloc: types.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
|
||||||
}
|
}
|
||||||
signer = types.LatestSigner(gspec.Config)
|
signer = types.LatestSigner(gspec.Config)
|
||||||
blobSigners = [6]struct {
|
|
||||||
key *ecdsa.PrivateKey
|
// Compute empty blob hash.
|
||||||
addr common.Address
|
emptyBlob = kzg4844.Blob{}
|
||||||
}{}
|
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
|
||||||
|
emptyBlobVHash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
|
||||||
)
|
)
|
||||||
config.LondonBlock = londonBlock
|
config.LondonBlock = londonBlock
|
||||||
config.ArrowGlacierBlock = londonBlock
|
config.ArrowGlacierBlock = londonBlock
|
||||||
config.GrayGlacierBlock = londonBlock
|
config.GrayGlacierBlock = londonBlock
|
||||||
var engine consensus.Engine = beacon.New(ethash.NewFaker())
|
var engine consensus.Engine = beacon.New(ethash.NewFaker())
|
||||||
td := int(params.GenesisDifficulty.Uint64())
|
td := params.GenesisDifficulty.Uint64()
|
||||||
|
|
||||||
if addCancunBlocks {
|
if cancunBlock != nil {
|
||||||
for i := range blobSigners {
|
ts := gspec.Timestamp + cancunBlock.Uint64()*10 // fixed 10 sec block time in blockgen
|
||||||
key, _ := crypto.GenerateKey()
|
config.ShanghaiTime = &ts
|
||||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
config.CancunTime = &ts
|
||||||
blobSigners[i].key = key
|
signer = types.LatestSigner(gspec.Config)
|
||||||
blobSigners[i].addr = addr
|
|
||||||
gspec.Alloc[addr] = types.Account{Balance: big.NewInt(math.MaxInt64)}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate testing blocks
|
// Generate testing blocks
|
||||||
genDb, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) {
|
db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) {
|
||||||
b.SetCoinbase(common.Address{1})
|
b.SetCoinbase(common.Address{1})
|
||||||
td += int(b.Difficulty().Uint64())
|
|
||||||
|
|
||||||
var txdata types.TxData
|
var txdata types.TxData
|
||||||
if londonBlock != nil && b.Number().Cmp(londonBlock) >= 0 {
|
if londonBlock != nil && b.Number().Cmp(londonBlock) >= 0 {
|
||||||
|
|
@ -187,61 +185,15 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool, addCancunB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
b.AddTx(types.MustSignNewTx(key, signer, txdata))
|
b.AddTx(types.MustSignNewTx(key, signer, txdata))
|
||||||
})
|
|
||||||
// Construct testing chain
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
|
||||||
merger := consensus.NewMerger(db)
|
|
||||||
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create local chain, %v", err)
|
|
||||||
}
|
|
||||||
if i, err := chain.InsertChain(blocks); err != nil {
|
|
||||||
panic(fmt.Errorf("error inserting block %d: %w", i, err))
|
|
||||||
}
|
|
||||||
chain.SetFinalized(chain.GetBlockByNumber(25).Header())
|
|
||||||
chain.SetSafe(chain.GetBlockByNumber(25).Header())
|
|
||||||
|
|
||||||
if addCancunBlocks {
|
if cancunBlock != nil && b.Number().Cmp(cancunBlock) >= 0 {
|
||||||
if err := chain.SetHead(26); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
head := chain.GetBlockByNumber(26)
|
|
||||||
ts := head.Time()
|
|
||||||
config.ShanghaiTime = &ts
|
|
||||||
config.CancunTime = &ts
|
|
||||||
ttd := chain.GetTd(head.Hash(), head.NumberU64())
|
|
||||||
config.TerminalTotalDifficulty = ttd
|
|
||||||
signer = types.LatestSigner(gspec.Config)
|
|
||||||
|
|
||||||
merger.ReachTTD()
|
|
||||||
merger.FinalizePoS()
|
|
||||||
|
|
||||||
var (
|
|
||||||
emptyBlob = kzg4844.Blob{}
|
|
||||||
emptyBlobCommit, _ = kzg4844.BlobToCommitment(emptyBlob)
|
|
||||||
emptyBlobVHash = kzg4844.CalcBlobHashV1(sha256.New(), &emptyBlobCommit)
|
|
||||||
)
|
|
||||||
|
|
||||||
postBlocks, _ := core.GenerateChain(gspec.Config, head, engine, genDb, 6+1, func(i int, b *core.BlockGen) {
|
|
||||||
b.SetPoS()
|
b.SetPoS()
|
||||||
|
|
||||||
txdata := &types.DynamicFeeTx{
|
|
||||||
ChainID: gspec.Config.ChainID,
|
|
||||||
Nonce: b.TxNonce(addr),
|
|
||||||
To: &common.Address{},
|
|
||||||
Gas: 30000,
|
|
||||||
GasFeeCap: big.NewInt(100 * params.GWei),
|
|
||||||
GasTipCap: big.NewInt(int64(i+1) * params.GWei),
|
|
||||||
Data: []byte{},
|
|
||||||
}
|
|
||||||
b.AddTx(types.MustSignNewTx(key, signer, txdata))
|
|
||||||
|
|
||||||
// put more blobs in each new block
|
// put more blobs in each new block
|
||||||
for j := 0; j < i && j < 6; j++ {
|
for j := 0; j < i && j < 6; j++ {
|
||||||
blobTx := &types.BlobTx{
|
blobTx := &types.BlobTx{
|
||||||
ChainID: uint256.MustFromBig(gspec.Config.ChainID),
|
ChainID: uint256.MustFromBig(gspec.Config.ChainID),
|
||||||
Nonce: b.TxNonce(blobSigners[j].addr),
|
Nonce: b.TxNonce(addr),
|
||||||
To: common.Address{},
|
To: common.Address{},
|
||||||
Gas: 30000,
|
Gas: 30000,
|
||||||
GasFeeCap: uint256.NewInt(100 * params.GWei),
|
GasFeeCap: uint256.NewInt(100 * params.GWei),
|
||||||
|
|
@ -252,14 +204,22 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool, addCancunB
|
||||||
Value: uint256.NewInt(100),
|
Value: uint256.NewInt(100),
|
||||||
Sidecar: nil,
|
Sidecar: nil,
|
||||||
}
|
}
|
||||||
b.AddTx(types.MustSignNewTx(blobSigners[j].key, signer, blobTx))
|
b.AddTx(types.MustSignNewTx(key, signer, blobTx))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
td += b.Difficulty().Uint64()
|
||||||
})
|
})
|
||||||
|
// Construct testing chain
|
||||||
if i, err := chain.InsertChain(postBlocks); err != nil {
|
gspec.Config.TerminalTotalDifficulty = new(big.Int).SetUint64(td)
|
||||||
|
chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, nil, engine, vm.Config{}, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create local chain, %v", err)
|
||||||
|
}
|
||||||
|
if i, err := chain.InsertChain(blocks); err != nil {
|
||||||
panic(fmt.Errorf("error inserting block %d: %w", i, err))
|
panic(fmt.Errorf("error inserting block %d: %w", i, err))
|
||||||
}
|
}
|
||||||
}
|
chain.SetFinalized(chain.GetBlockByNumber(25).Header())
|
||||||
|
chain.SetSafe(chain.GetBlockByNumber(25).Header())
|
||||||
|
|
||||||
return &testBackend{chain: chain, pending: pending}
|
return &testBackend{chain: chain, pending: pending}
|
||||||
}
|
}
|
||||||
|
|
@ -289,7 +249,7 @@ func TestSuggestTipCap(t *testing.T) {
|
||||||
{big.NewInt(33), big.NewInt(params.GWei * int64(30))}, // Fork point in the future
|
{big.NewInt(33), big.NewInt(params.GWei * int64(30))}, // Fork point in the future
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
backend := newTestBackend(t, c.fork, false, false)
|
backend := newTestBackend(t, c.fork, nil, false)
|
||||||
oracle := NewOracle(backend, config)
|
oracle := NewOracle(backend, config)
|
||||||
|
|
||||||
// The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G
|
// The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue