eth, miner: fix enforcing the minimum miner tip (#28933) (#1209)

* eth, miner: fix enforcing the minimum miner tip

* ethclient/simulated: fix failing test due the min tip change

* accounts/abi/bind: fix simulater gas tip issue

Co-authored-by: Péter Szilágyi <peterke@gmail.com>
This commit is contained in:
Pratik Patil 2024-04-08 10:47:47 +05:30 committed by GitHub
parent 694eadb94d
commit ee7299bb24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 39 additions and 13 deletions

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
) )
var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@ -64,7 +65,7 @@ func TestWaitDeployed(t *testing.T) {
// Create the transaction // Create the transaction
head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough head, _ := backend.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1)) gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code)) tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code))
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)

View file

@ -64,6 +64,7 @@ func (api *MinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
api.e.lock.Unlock() api.e.lock.Unlock()
api.e.txPool.SetGasTip((*big.Int)(&gasPrice)) api.e.txPool.SetGasTip((*big.Int)(&gasPrice))
api.e.Miner().SetGasTip((*big.Int)(&gasPrice))
return true return true
} }

View file

@ -219,6 +219,11 @@ func (miner *Miner) SetExtra(extra []byte) error {
return nil return nil
} }
func (miner *Miner) SetGasTip(tip *big.Int) error {
miner.worker.setGasTip(tip)
return nil
}
// SetRecommitInterval sets the interval for sealing work resubmitting. // SetRecommitInterval sets the interval for sealing work resubmitting.
func (miner *Miner) SetRecommitInterval(interval time.Duration) { func (miner *Miner) SetRecommitInterval(interval time.Duration) {
miner.worker.setRecommitInterval(interval) miner.worker.setRecommitInterval(interval)

View file

@ -119,11 +119,11 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
} }
// Peek returns the next transaction by price. // Peek returns the next transaction by price.
func (t *transactionsByPriceAndNonce) Peek() *txpool.LazyTransaction { func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *big.Int) {
if len(t.heads) == 0 { if len(t.heads) == 0 {
return nil return nil, nil
} }
return t.heads[0].tx return t.heads[0].tx, t.heads[0].fees
} }
// Shift replaces the current best head with the next one from the same account. // Shift replaces the current best head with the next one from the same account.

View file

@ -102,7 +102,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
txset := newTransactionsByPriceAndNonce(signer, groups, baseFee) txset := newTransactionsByPriceAndNonce(signer, groups, baseFee)
txs := types.Transactions{} txs := types.Transactions{}
for tx := txset.Peek(); tx != nil; tx = txset.Peek() { for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() {
txs = append(txs, tx.Tx) txs = append(txs, tx.Tx)
txset.Shift() txset.Shift()
} }
@ -167,7 +167,7 @@ func TestTransactionTimeSort(t *testing.T) {
txset := newTransactionsByPriceAndNonce(signer, groups, nil) txset := newTransactionsByPriceAndNonce(signer, groups, nil)
txs := types.Transactions{} txs := types.Transactions{}
for tx := txset.Peek(); tx != nil; tx = txset.Peek() { for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() {
txs = append(txs, tx.Tx) txs = append(txs, tx.Tx)
txset.Shift() txset.Shift()
} }

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math/big"
"os" "os"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -175,7 +176,7 @@ func (w *worker) mainLoopWithDelay(ctx context.Context, delay uint, opcodeDelay
} }
txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
tcount := w.current.tcount tcount := w.current.tcount
w.commitTransactions(w.current, txset, nil, context.Background()) w.commitTransactions(w.current, txset, nil, new(big.Int), context.Background())
// Only update the snapshot if any new transactons were added // Only update the snapshot if any new transactons were added
// to the pending block // to the pending block
@ -587,7 +588,7 @@ mainloop:
break break
} }
// Retrieve the next transaction and abort if all done. // Retrieve the next transaction and abort if all done.
ltx := txs.Peek() ltx, _ := txs.Peek()
if ltx == nil { if ltx == nil {
breakCause = "all transactions has been included" breakCause = "all transactions has been included"
break break

View file

@ -237,6 +237,7 @@ type worker struct {
mu sync.RWMutex // The lock used to protect the coinbase and extra fields mu sync.RWMutex // The lock used to protect the coinbase and extra fields
coinbase common.Address coinbase common.Address
extra []byte extra []byte
tip *big.Int // Minimum tip needed for non-local transaction to include them
pendingMu sync.RWMutex pendingMu sync.RWMutex
pendingTasks map[common.Hash]*task pendingTasks map[common.Hash]*task
@ -295,6 +296,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
isLocalBlock: isLocalBlock, isLocalBlock: isLocalBlock,
coinbase: config.Etherbase, coinbase: config.Etherbase,
extra: config.ExtraData, extra: config.ExtraData,
tip: config.GasPrice,
pendingTasks: make(map[common.Hash]*task), pendingTasks: make(map[common.Hash]*task),
txsCh: make(chan core.NewTxsEvent, txChanSize), txsCh: make(chan core.NewTxsEvent, txChanSize),
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
@ -395,6 +397,13 @@ func (w *worker) setExtra(extra []byte) {
w.extra = extra w.extra = extra
} }
// setGasTip sets the minimum miner tip needed to include a non-local transaction.
func (w *worker) setGasTip(tip *big.Int) {
w.mu.Lock()
defer w.mu.Unlock()
w.tip = tip
}
// setRecommitInterval updates the interval for miner sealing work recommitting. // setRecommitInterval updates the interval for miner sealing work recommitting.
func (w *worker) setRecommitInterval(interval time.Duration) { func (w *worker) setRecommitInterval(interval time.Duration) {
select { select {
@ -648,7 +657,7 @@ func (w *worker) mainLoop(ctx context.Context) {
} }
txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee) txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
tcount := w.current.tcount tcount := w.current.tcount
w.commitTransactions(w.current, txset, nil, context.Background()) w.commitTransactions(w.current, txset, nil, new(big.Int), context.Background())
// Only update the snapshot if any new transactons were added // Only update the snapshot if any new transactons were added
// to the pending block // to the pending block
@ -908,7 +917,7 @@ func (w *worker) commitTransaction(env *environment, tx *types.Transaction, inte
return receipt.Logs, nil return receipt.Logs, nil
} }
func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32, interruptCtx context.Context) error { func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32, minTip *big.Int, interruptCtx context.Context) error {
gasLimit := env.header.GasLimit gasLimit := env.header.GasLimit
if env.gasPool == nil { if env.gasPool == nil {
env.gasPool = new(core.GasPool).AddGas(gasLimit) env.gasPool = new(core.GasPool).AddGas(gasLimit)
@ -996,7 +1005,7 @@ mainloop:
break break
} }
// Retrieve the next transaction and abort if all done. // Retrieve the next transaction and abort if all done.
ltx := txs.Peek() ltx, tip := txs.Peek()
if ltx == nil { if ltx == nil {
breakCause = "all transactions has been included" breakCause = "all transactions has been included"
break break
@ -1012,6 +1021,11 @@ mainloop:
txs.Pop() txs.Pop()
continue continue
} }
// If we don't receive enough tip for the next transaction, skip the account
if tip.Cmp(minTip) < 0 {
log.Trace("Not enough tip for transaction", "hash", ltx.Hash, "tip", tip, "needed", minTip)
break // If the next-best is too low, surely no better will be available
}
// Transaction seems to fit, pull it up from the pool // Transaction seems to fit, pull it up from the pool
tx := ltx.Resolve() tx := ltx.Resolve()
if tx == nil { if tx == nil {
@ -1469,6 +1483,10 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
err error err error
) )
w.mu.RLock()
tip := w.tip
w.mu.RUnlock()
if len(localTxs) > 0 { if len(localTxs) > 0 {
var txs *transactionsByPriceAndNonce var txs *transactionsByPriceAndNonce
@ -1487,7 +1505,7 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
}) })
tracing.Exec(ctx, "", "worker.LocalCommitTransactions", func(ctx context.Context, span trace.Span) { tracing.Exec(ctx, "", "worker.LocalCommitTransactions", func(ctx context.Context, span trace.Span) {
err = w.commitTransactions(env, txs, interrupt, interruptCtx) err = w.commitTransactions(env, txs, interrupt, new(big.Int), interruptCtx)
}) })
if err != nil { if err != nil {
@ -1515,7 +1533,7 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32,
}) })
tracing.Exec(ctx, "", "worker.RemoteCommitTransactions", func(ctx context.Context, span trace.Span) { tracing.Exec(ctx, "", "worker.RemoteCommitTransactions", func(ctx context.Context, span trace.Span) {
err = w.commitTransactions(env, txs, interrupt, interruptCtx) err = w.commitTransactions(env, txs, interrupt, tip, interruptCtx)
}) })
if err != nil { if err != nil {