core, miner: polish

This commit is contained in:
Gary Rong 2025-06-11 21:22:29 +08:00
parent af879b0ebf
commit e2420abbc3
8 changed files with 42 additions and 64 deletions

View file

@ -85,7 +85,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
var blobs int
for i, tx := range block.Transactions() {
if v.config.IsOsaka(block.Number(), block.Time()) && tx.Gas() > params.MaxTxGas {
return fmt.Errorf("transaction exceeds maximum allowed gas limit (has %d gas)", tx.Gas())
return fmt.Errorf("%w (cap: %d, tx: %d)", ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas())
}
// Count the number of blobs to validate against the header's blobGasUsed

View file

@ -122,6 +122,9 @@ var (
// Message validation errors:
ErrEmptyAuthList = errors.New("EIP-7702 transaction with empty auth list")
ErrSetCodeTxCreate = errors.New("EIP-7702 transaction cannot be used to create contract")
// -- EIP-7825 errors --
ErrGasLimitTooHigh = errors.New("transaction gas limit too high")
)
// EIP-7702 state transition errors.

View file

@ -1638,6 +1638,11 @@ func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx
break // blobfee too low, cannot be included, discard rest of txs from the account
}
}
if filter.GasLimitCap != 0 {
if tx.execGas > filter.GasLimitCap {
break // execution gas limit is too high
}
}
// Transaction was accepted according to the filter, append to the pending list
lazies = append(lazies, &txpool.LazyTransaction{
Pool: p,

View file

@ -531,11 +531,19 @@ func (pool *LegacyPool) Pending(filter txpool.PendingFilter) map[common.Address]
txs := list.Flatten()
// If the miner requests tip enforcement, cap the lists now
if minTipBig != nil {
if minTipBig != nil || filter.GasLimitCap != 0 {
for i, tx := range txs {
if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 {
txs = txs[:i]
break
if minTipBig != nil {
if tx.EffectiveGasTipIntCmp(minTipBig, baseFeeBig) < 0 {
txs = txs[:i]
break
}
}
if filter.GasLimitCap != 0 {
if tx.Gas() > filter.GasLimitCap {
txs = txs[:i]
break
}
}
}
}
@ -1263,16 +1271,17 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest,
pool.mu.Lock()
if reset != nil {
if reset.newHead != nil && reset.oldHead != nil {
// Discard the transactions with the gas limit higher than the cap.
if pool.chainconfig.IsOsaka(reset.newHead.Number, reset.newHead.Time) && !pool.chainconfig.IsOsaka(reset.oldHead.Number, reset.oldHead.Time) {
var removeHashes []common.Hash
var hashes []common.Hash
pool.all.Range(func(hash common.Hash, tx *types.Transaction) bool {
if tx.Gas() > params.MaxTxGas {
removeHashes = append(removeHashes, hash)
hashes = append(hashes, hash)
}
return true
})
for _, hash := range removeHashes {
pool.all.Remove(hash)
for _, hash := range hashes {
pool.removeTx(hash, true, true)
}
}
}

View file

@ -74,9 +74,10 @@ type LazyResolver interface {
// a very specific call site in mind and each one can be evaluated very cheaply
// by the pool implementations. Only add new ones that satisfy those constraints.
type PendingFilter struct {
MinTip *uint256.Int // Minimum miner tip required to include a transaction
BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction
BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction
MinTip *uint256.Int // Minimum miner tip required to include a transaction
BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction
BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction
GasLimitCap uint64 // Maximum gas can be used for a single transaction execution (0 means no limit)
OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling)
OnlyBlobTxs bool // Return only blob transactions (block blob-space filling)

View file

@ -76,9 +76,6 @@ type TxPool struct {
term chan struct{} // Termination channel to detect a closed pool
sync chan chan error // Testing / simulator channel to block until internal reset is done
headLock sync.RWMutex
head *types.Header // this reflects the state from the latest pool reset
}
// New creates a new transaction pool to gather, sort and filter inbound
@ -107,7 +104,6 @@ func New(gasTip uint64, chain BlockChain, subpools []SubPool) (*TxPool, error) {
quit: make(chan chan error),
term: make(chan struct{}),
sync: make(chan chan error),
head: head,
}
reserver := NewReservationTracker()
for i, subpool := range subpools {
@ -207,9 +203,6 @@ func (p *TxPool) loop(head *types.Header) {
}
select {
case resetDone <- newHead:
p.headLock.Lock()
p.head = newHead
p.headLock.Unlock()
case <-p.term:
}
}(oldHead, newHead)
@ -264,14 +257,6 @@ func (p *TxPool) loop(head *types.Header) {
errc <- nil
}
// Head returns the header which corresponds to the most recent successful pool
// reset.
func (p *TxPool) Head() *types.Header {
p.headLock.RLock()
defer p.headLock.RUnlock()
return types.CopyHeader(p.head)
}
// SetGasTip updates the minimum gas tip required by the transaction pool for a
// new transaction, and drops all transactions below this threshold.
func (p *TxPool) SetGasTip(tip *big.Int) {

View file

@ -87,7 +87,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize)
}
if rules.IsOsaka && tx.Gas() > params.MaxTxGas {
return fmt.Errorf("transaction gas exceeded max allowed (%d): %d", params.MaxTxGas, tx.Gas())
return fmt.Errorf("%w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas())
}
// Transactions can't be negative. This may never happen using RLP decoded
// transactions but may occur for transactions created using the RPC.

View file

@ -59,8 +59,7 @@ type environment struct {
sidecars []*types.BlobTxSidecar
blobs int
witness *stateless.Witness
chainConfig *params.ChainConfig
witness *stateless.Witness
}
const (
@ -254,13 +253,12 @@ func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase
}
// Note the passed coinbase may be different with header.Coinbase.
return &environment{
signer: types.MakeSigner(miner.chainConfig, header.Number, header.Time),
state: state,
coinbase: coinbase,
header: header,
witness: state.Witness(),
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
chainConfig: miner.chainConfig,
signer: types.MakeSigner(miner.chainConfig, header.Number, header.Time),
state: state,
coinbase: coinbase,
header: header,
witness: state.Witness(),
evm: vm.NewEVM(core.NewEVMBlockContext(header, miner.chain, &coinbase), state, miner.chainConfig, vm.Config{}),
}, nil
}
@ -427,23 +425,6 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran
return nil
}
// fiterTxsAboveGas removes any transactions from the set which exceed a gas threshold.
// If a transaction is removed, all higher-nonce transactions from the same account
// will also be filtered out.
func filterTxsAboveGas(txs map[common.Address][]*txpool.LazyTransaction, maxGas uint64) {
for sender, senderTxs := range txs {
for i, tx := range senderTxs {
if tx.Gas > maxGas {
if i == 0 {
delete(txs, sender)
} else {
txs[sender] = txs[sender][:i]
}
}
}
}
}
// fillTransactions retrieves the pending transactions from the txpool and fills them
// into the given sealing block. The transaction selection and ordering strategy can
// be customized with the plugin in the future.
@ -463,7 +444,11 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
if env.header.ExcessBlobGas != nil {
filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(miner.chainConfig, env.header))
}
if miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) {
filter.GasLimitCap = params.MaxTxGas
}
filter.OnlyPlainTxs, filter.OnlyBlobTxs = true, false
pendingPlainTxs := miner.txpool.Pending(filter)
filter.OnlyPlainTxs, filter.OnlyBlobTxs = false, true
@ -473,16 +458,6 @@ func (miner *Miner) fillTransactions(interrupt *atomic.Int32, env *environment)
prioPlainTxs, normalPlainTxs := make(map[common.Address][]*txpool.LazyTransaction), pendingPlainTxs
prioBlobTxs, normalBlobTxs := make(map[common.Address][]*txpool.LazyTransaction), pendingBlobTxs
// if we have just entered the Osaka fork, it is possible due to the async
// nature of txpool resets that the state of the pool has not finished resetting
// to a post-fork block. If so, it may not have removed txs that exceed the
// eip-7825 transaction maximum gas limit.
poolHead := miner.txpool.Head()
if env.chainConfig.IsOsaka(env.header.Number, env.header.Time) && !env.chainConfig.IsOsaka(poolHead.Number, poolHead.Time) {
filterTxsAboveGas(prioPlainTxs, params.MaxTxGas)
filterTxsAboveGas(prioBlobTxs, params.MaxTxGas)
}
for _, account := range prio {
if txs := normalPlainTxs[account]; len(txs) > 0 {
delete(normalPlainTxs, account)