Skip to content

Commit 16ce7bf

Browse files
authored
eth, miner: fix enforcing the minimum miner tip (#28933)
* 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
1 parent 0b5d8d2 commit 16ce7bf

File tree

8 files changed

+53
-13
lines changed

8 files changed

+53
-13
lines changed

accounts/abi/bind/util_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func TestWaitDeployed(t *testing.T) {
6565

6666
// Create the transaction
6767
head, _ := backend.Client().HeaderByNumber(context.Background(), nil) // Should be child's, good enough
68-
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
68+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
6969

7070
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, gasPrice, common.FromHex(test.code))
7171
tx, _ = types.SignTx(tx, types.LatestSignerForChainID(big.NewInt(1337)), testKey)

eth/api_miner.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ func (api *MinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
6464
api.e.lock.Unlock()
6565

6666
api.e.txPool.SetGasTip((*big.Int)(&gasPrice))
67+
api.e.Miner().SetGasTip((*big.Int)(&gasPrice))
6768
return true
6869
}
6970

ethclient/simulated/backend_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func newTx(sim *Backend, key *ecdsa.PrivateKey) (*types.Transaction, error) {
5252

5353
// create a signed transaction to send
5454
head, _ := client.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
55-
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
55+
gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(params.GWei))
5656
addr := crypto.PubkeyToAddress(key.PublicKey)
5757
chainid, _ := client.ChainID(context.Background())
5858
nonce, err := client.PendingNonceAt(context.Background(), addr)
@@ -62,7 +62,7 @@ func newTx(sim *Backend, key *ecdsa.PrivateKey) (*types.Transaction, error) {
6262
tx := types.NewTx(&types.DynamicFeeTx{
6363
ChainID: chainid,
6464
Nonce: nonce,
65-
GasTipCap: big.NewInt(1),
65+
GasTipCap: big.NewInt(params.GWei),
6666
GasFeeCap: gasPrice,
6767
Gas: 21000,
6868
To: &addr,

ethclient/simulated/options.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package simulated
1818

1919
import (
20+
"math/big"
21+
2022
"github.com/ethereum/go-ethereum/eth/ethconfig"
2123
"github.com/ethereum/go-ethereum/node"
2224
)
@@ -37,3 +39,17 @@ func WithCallGasLimit(gaslimit uint64) func(nodeConf *node.Config, ethConf *ethc
3739
ethConf.RPCGasCap = gaslimit
3840
}
3941
}
42+
43+
// WithMinerMinTip configures the simulated backend to require a specific minimum
44+
// gas tip for a transaction to be included.
45+
//
46+
// 0 is not possible as a live Geth node would reject that due to DoS protection,
47+
// so the simulated backend will replicate that behavior for consisntency.
48+
func WithMinerMinTip(tip *big.Int) func(nodeConf *node.Config, ethConf *ethconfig.Config) {
49+
if tip == nil || tip.Cmp(new(big.Int)) <= 0 {
50+
panic("invalid miner minimum tip")
51+
}
52+
return func(nodeConf *node.Config, ethConf *ethconfig.Config) {
53+
ethConf.Miner.GasPrice = tip
54+
}
55+
}

miner/miner.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ func (miner *Miner) SetExtra(extra []byte) error {
197197
return nil
198198
}
199199

200+
func (miner *Miner) SetGasTip(tip *big.Int) error {
201+
miner.worker.setGasTip(tip)
202+
return nil
203+
}
204+
200205
// SetRecommitInterval sets the interval for sealing work resubmitting.
201206
func (miner *Miner) SetRecommitInterval(interval time.Duration) {
202207
miner.worker.setRecommitInterval(interval)

miner/ordering.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,11 @@ func newTransactionsByPriceAndNonce(signer types.Signer, txs map[common.Address]
119119
}
120120

121121
// Peek returns the next transaction by price.
122-
func (t *transactionsByPriceAndNonce) Peek() *txpool.LazyTransaction {
122+
func (t *transactionsByPriceAndNonce) Peek() (*txpool.LazyTransaction, *big.Int) {
123123
if len(t.heads) == 0 {
124-
return nil
124+
return nil, nil
125125
}
126-
return t.heads[0].tx
126+
return t.heads[0].tx, t.heads[0].fees
127127
}
128128

129129
// Shift replaces the current best head with the next one from the same account.

miner/ordering_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) {
104104
txset := newTransactionsByPriceAndNonce(signer, groups, baseFee)
105105

106106
txs := types.Transactions{}
107-
for tx := txset.Peek(); tx != nil; tx = txset.Peek() {
107+
for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() {
108108
txs = append(txs, tx.Tx)
109109
txset.Shift()
110110
}
@@ -170,7 +170,7 @@ func TestTransactionTimeSort(t *testing.T) {
170170
txset := newTransactionsByPriceAndNonce(signer, groups, nil)
171171

172172
txs := types.Transactions{}
173-
for tx := txset.Peek(); tx != nil; tx = txset.Peek() {
173+
for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() {
174174
txs = append(txs, tx.Tx)
175175
txset.Shift()
176176
}

miner/worker.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ type worker struct {
205205
mu sync.RWMutex // The lock used to protect the coinbase and extra fields
206206
coinbase common.Address
207207
extra []byte
208+
tip *big.Int // Minimum tip needed for non-local transaction to include them
208209

209210
pendingMu sync.RWMutex
210211
pendingTasks map[common.Hash]*task
@@ -251,6 +252,7 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
251252
isLocalBlock: isLocalBlock,
252253
coinbase: config.Etherbase,
253254
extra: config.ExtraData,
255+
tip: config.GasPrice,
254256
pendingTasks: make(map[common.Hash]*task),
255257
txsCh: make(chan core.NewTxsEvent, txChanSize),
256258
chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
@@ -327,6 +329,13 @@ func (w *worker) setExtra(extra []byte) {
327329
w.extra = extra
328330
}
329331

332+
// setGasTip sets the minimum miner tip needed to include a non-local transaction.
333+
func (w *worker) setGasTip(tip *big.Int) {
334+
w.mu.Lock()
335+
defer w.mu.Unlock()
336+
w.tip = tip
337+
}
338+
330339
// setRecommitInterval updates the interval for miner sealing work recommitting.
331340
func (w *worker) setRecommitInterval(interval time.Duration) {
332341
select {
@@ -554,7 +563,7 @@ func (w *worker) mainLoop() {
554563
}
555564
txset := newTransactionsByPriceAndNonce(w.current.signer, txs, w.current.header.BaseFee)
556565
tcount := w.current.tcount
557-
w.commitTransactions(w.current, txset, nil)
566+
w.commitTransactions(w.current, txset, nil, new(big.Int))
558567

559568
// Only update the snapshot if any new transactions were added
560569
// to the pending block
@@ -792,7 +801,7 @@ func (w *worker) applyTransaction(env *environment, tx *types.Transaction) (*typ
792801
return receipt, err
793802
}
794803

795-
func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32) error {
804+
func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAndNonce, interrupt *atomic.Int32, minTip *big.Int) error {
796805
gasLimit := env.header.GasLimit
797806
if env.gasPool == nil {
798807
env.gasPool = new(core.GasPool).AddGas(gasLimit)
@@ -812,7 +821,7 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
812821
break
813822
}
814823
// Retrieve the next transaction and abort if all done.
815-
ltx := txs.Peek()
824+
ltx, tip := txs.Peek()
816825
if ltx == nil {
817826
break
818827
}
@@ -827,6 +836,11 @@ func (w *worker) commitTransactions(env *environment, txs *transactionsByPriceAn
827836
txs.Pop()
828837
continue
829838
}
839+
// If we don't receive enough tip for the next transaction, skip the account
840+
if tip.Cmp(minTip) < 0 {
841+
log.Trace("Not enough tip for transaction", "hash", ltx.Hash, "tip", tip, "needed", minTip)
842+
break // If the next-best is too low, surely no better will be available
843+
}
830844
// Transaction seems to fit, pull it up from the pool
831845
tx := ltx.Resolve()
832846
if tx == nil {
@@ -997,15 +1011,19 @@ func (w *worker) fillTransactions(interrupt *atomic.Int32, env *environment) err
9971011
}
9981012

9991013
// Fill the block with all available pending transactions.
1014+
w.mu.RLock()
1015+
tip := w.tip
1016+
w.mu.RUnlock()
1017+
10001018
if len(localTxs) > 0 {
10011019
txs := newTransactionsByPriceAndNonce(env.signer, localTxs, env.header.BaseFee)
1002-
if err := w.commitTransactions(env, txs, interrupt); err != nil {
1020+
if err := w.commitTransactions(env, txs, interrupt, new(big.Int)); err != nil {
10031021
return err
10041022
}
10051023
}
10061024
if len(remoteTxs) > 0 {
10071025
txs := newTransactionsByPriceAndNonce(env.signer, remoteTxs, env.header.BaseFee)
1008-
if err := w.commitTransactions(env, txs, interrupt); err != nil {
1026+
if err := w.commitTransactions(env, txs, interrupt, tip); err != nil {
10091027
return err
10101028
}
10111029
}

0 commit comments

Comments
 (0)