txpool: limit max gas when mining is enabled; (#2435)

This commit is contained in:
galaio 2024-05-09 15:54:31 +08:00 committed by GitHub
parent 901ea2e0d2
commit 7bc5a3353d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 58 additions and 0 deletions

@ -25,6 +25,8 @@ import (
"strings"
"time"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/cmd/utils"
@ -456,6 +458,10 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
// Set the gas price to the limits from the CLI and start mining
gasprice := flags.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
ethBackend.TxPool().SetGasTip(gasprice)
gasCeil := ethBackend.Miner().GasCeil()
if gasCeil > params.SystemTxsGas {
ethBackend.TxPool().SetMaxGas(gasCeil - params.SystemTxsGas)
}
if err := ethBackend.StartMining(); err != nil {
utils.Fatalf("Failed to start mining: %v", err)
}

@ -27,6 +27,7 @@ import (
"path/filepath"
"sort"
"sync"
"sync/atomic"
"time"
"github.com/ethereum/go-ethereum/common"
@ -305,6 +306,7 @@ type BlobPool struct {
head *types.Header // Current head of the chain
state *state.StateDB // Current state at the head of the chain
gasTip *uint256.Int // Currently accepted minimum gas tip
maxGas atomic.Uint64 // Currently accepted max gas, it will be modified by MinerAPI
lookup map[common.Hash]uint64 // Lookup table mapping hashes to tx billy entries
index map[common.Address][]*blobTxMeta // Blob transactions grouped by accounts, sorted by nonce
@ -1098,6 +1100,7 @@ func (p *BlobPool) validateTx(tx *types.Transaction) error {
Accept: 1 << types.BlobTxType,
MaxSize: txMaxSize,
MinTip: p.gasTip.ToBig(),
MaxGas: p.GetMaxGas(),
}
if err := txpool.ValidateTransaction(tx, p.head, p.signer, baseOpts); err != nil {
return err
@ -1671,3 +1674,11 @@ func (p *BlobPool) Status(hash common.Hash) txpool.TxStatus {
}
return txpool.TxStatusUnknown
}
func (p *BlobPool) SetMaxGas(maxGas uint64) {
p.maxGas.Store(maxGas)
}
func (p *BlobPool) GetMaxGas() uint64 {
return p.maxGas.Load()
}

@ -219,6 +219,7 @@ type LegacyPool struct {
scope event.SubscriptionScope
signer types.Signer
mu sync.RWMutex
maxGas atomic.Uint64 // Currently accepted max gas, it will be modified by MinerAPI
currentHead atomic.Pointer[types.Header] // Current head of the blockchain
currentState *state.StateDB // Current state in the blockchain head
@ -670,6 +671,7 @@ func (pool *LegacyPool) validateTxBasics(tx *types.Transaction, local bool) erro
1<<types.DynamicFeeTxType,
MaxSize: txMaxSize,
MinTip: pool.gasTip.Load().ToBig(),
MaxGas: pool.GetMaxGas(),
}
if local {
opts.MinTip = new(big.Int)
@ -1769,6 +1771,14 @@ func (pool *LegacyPool) demoteUnexecutables() {
}
}
func (pool *LegacyPool) GetMaxGas() uint64 {
return pool.maxGas.Load()
}
func (pool *LegacyPool) SetMaxGas(maxGas uint64) {
pool.maxGas.Store(maxGas)
}
// addressByHeartbeat is an account address tagged with its last activity timestamp.
type addressByHeartbeat struct {
address common.Address

@ -166,4 +166,7 @@ type SubPool interface {
// Status returns the known status (unknown/pending/queued) of a transaction
// identified by their hashes.
Status(hash common.Hash) TxStatus
// SetMaxGas limit max acceptable tx gas when mine is enabled
SetMaxGas(maxGas uint64)
}

@ -284,6 +284,12 @@ func (p *TxPool) SetGasTip(tip *big.Int) {
}
}
func (p *TxPool) SetMaxGas(gas uint64) {
for _, subpool := range p.subpools {
subpool.SetMaxGas(gas)
}
}
// Has returns an indicator whether the pool has a transaction cached with the
// given hash.
func (p *TxPool) Has(hash common.Hash) bool {

@ -45,6 +45,7 @@ type ValidationOptions struct {
Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool
MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle
MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool
MaxGas uint64 // Max acceptable transaction gas in the txpool
}
// ValidateTransaction is a helper method to check whether a transaction is valid
@ -86,6 +87,12 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
if head.GasLimit < tx.Gas() {
return ErrGasLimit
}
// Ensure the transaction doesn't exceed the current miner max acceptable limit gas
if opts.MaxGas > 0 && opts.MaxGas < tx.Gas() {
return ErrGasLimit
}
// Sanity check for extremely large numbers (supported by RLP or RPC)
if tx.GasFeeCap().BitLen() > 256 {
return core.ErrFeeCapVeryHigh

@ -20,6 +20,8 @@ import (
"math/big"
"time"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
@ -71,6 +73,9 @@ func (api *MinerAPI) SetGasPrice(gasPrice hexutil.Big) bool {
// SetGasLimit sets the gaslimit to target towards during mining.
func (api *MinerAPI) SetGasLimit(gasLimit hexutil.Uint64) bool {
api.e.Miner().SetGasCeil(uint64(gasLimit))
if api.e.Miner().Mining() && uint64(gasLimit) > params.SystemTxsGas {
api.e.TxPool().SetMaxGas(uint64(gasLimit) - params.SystemTxsGas)
}
return true
}

@ -295,3 +295,7 @@ func (miner *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscript
func (miner *Miner) BuildPayload(args *BuildPayloadArgs) (*Payload, error) {
return miner.worker.buildPayload(args)
}
func (miner *Miner) GasCeil() uint64 {
return miner.worker.getGasCeil()
}

@ -329,6 +329,12 @@ func (w *worker) setGasCeil(ceil uint64) {
w.config.GasCeil = ceil
}
func (w *worker) getGasCeil() uint64 {
w.mu.Lock()
defer w.mu.Unlock()
return w.config.GasCeil
}
// setExtra sets the content used to initialize the block extra field.
func (w *worker) setExtra(extra []byte) {
w.mu.Lock()