diff --git a/core/tx_pool.go b/core/tx_pool.go index 6b010c292a..16b5c60a9b 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -29,6 +29,7 @@ import ( "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common/prque" "github.com/XinFinOrg/XDPoSChain/consensus" + "github.com/XinFinOrg/XDPoSChain/consensus/misc" "github.com/XinFinOrg/XDPoSChain/core/state" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/event" @@ -537,13 +538,30 @@ func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common // Pending retrieves all currently processable transactions, grouped by origin // account and sorted by nonce. The returned transaction set is a copy and can be // freely modified by calling code. -func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) { +// +// The enforceTips parameter can be used to do an extra filtering on the pending +// transactions and only return those whose **effective** tip is large enough in +// the next pending execution environment. +func (pool *TxPool) Pending(enforceTips bool) (map[common.Address]types.Transactions, error) { pool.mu.Lock() defer pool.mu.Unlock() pending := make(map[common.Address]types.Transactions) for addr, list := range pool.pending { - pending[addr] = list.Flatten() + txs := list.Flatten() + + // If the miner requests tip enforcement, cap the lists now + if enforceTips && !pool.locals.contains(addr) { + for i, tx := range txs { + if tx.EffectiveTipIntCmp(pool.gasPrice, pool.priced.urgent.baseFee) < 0 { + txs = txs[:i] + break + } + } + } + if len(txs) > 0 { + pending[addr] = txs + } } return pending, nil } @@ -619,7 +637,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if tx.Tip().BitLen() > 256 { return ErrTipVeryHigh } - // Ensure feeCap is less than or equal to tip. + // Ensure feeCap is greater than or equal to tip. if tx.FeeCapIntCmp(tx.Tip()) < 0 { return ErrTipAboveFeeCap } @@ -1269,8 +1287,9 @@ func (pool *TxPool) runReorg(done chan struct{}, reset *txpoolResetRequest, dirt // because of another transaction (e.g. higher gas price). if reset != nil { pool.demoteUnexecutables() - if reset.newHead != nil { - pool.priced.SetBaseFee(reset.newHead.BaseFee) + if reset.newHead != nil && pool.chainconfig.IsEIP1559(new(big.Int).Add(reset.newHead.Number, big.NewInt(1))) { + pendingBaseFee := misc.CalcBaseFee(pool.chainconfig, reset.newHead) + pool.priced.SetBaseFee(pendingBaseFee) } } // Ensure pool.queue and pool.pending sizes stay within the configured limits. diff --git a/core/tx_pool_test.go b/core/tx_pool_test.go index 3a3766c26c..45b6156890 100644 --- a/core/tx_pool_test.go +++ b/core/tx_pool_test.go @@ -272,7 +272,7 @@ func TestStateChangeDuringTransactionPoolReset(t *testing.T) { trigger = true <-pool.requestReset(nil, nil) - _, err := pool.Pending() + _, err := pool.Pending(false) if err != nil { t.Fatalf("Could not fetch pending transactions: %v", err) } diff --git a/core/types/transaction.go b/core/types/transaction.go index 453d0ba43c..68d67ea5f6 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -384,6 +384,14 @@ func (tx *Transaction) EffectiveTipCmp(other *Transaction, baseFee *big.Int) int return tx.EffectiveTipValue(baseFee).Cmp(other.EffectiveTipValue(baseFee)) } +// EffectiveTipIntCmp compares the effective tip of a transaction to the given tip. +func (tx *Transaction) EffectiveTipIntCmp(other *big.Int, baseFee *big.Int) int { + if baseFee == nil { + return tx.TipIntCmp(other) + } + return tx.EffectiveTipValue(baseFee).Cmp(other) +} + // Hash returns the transaction hash. func (tx *Transaction) Hash() common.Hash { if hash := tx.hash.Load(); hash != nil { diff --git a/eth/api_backend.go b/eth/api_backend.go index fb3cefd455..cd395b364f 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -298,7 +298,7 @@ func (b *EthApiBackend) SendLendingTx(ctx context.Context, signedTx *types.Lendi } func (b *EthApiBackend) GetPoolTransactions() (types.Transactions, error) { - pending, err := b.eth.txPool.Pending() + pending, err := b.eth.txPool.Pending(false) if err != nil { return nil, err } diff --git a/eth/helper_test.go b/eth/helper_test.go index 4963093c1a..de175bbcee 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -111,7 +111,7 @@ func (p *testTxPool) AddRemotes(txs []*types.Transaction) []error { } // Pending returns all the transactions known to the pool -func (p *testTxPool) Pending() (map[common.Address]types.Transactions, error) { +func (p *testTxPool) Pending(enforceTips bool) (map[common.Address]types.Transactions, error) { p.lock.RLock() defer p.lock.RUnlock() diff --git a/eth/protocol.go b/eth/protocol.go index eb7297a28c..3876133e83 100644 --- a/eth/protocol.go +++ b/eth/protocol.go @@ -108,7 +108,7 @@ type txPool interface { // Pending should return pending transactions. // The slice should be modifiable by the caller. - Pending() (map[common.Address]types.Transactions, error) + Pending(enforceTips bool) (map[common.Address]types.Transactions, error) // SubscribeNewTxsEvent should return an event subscription of // NewTxsEvent and send events to the given channel. diff --git a/eth/sync.go b/eth/sync.go index cbe6d421c8..76edb614fb 100644 --- a/eth/sync.go +++ b/eth/sync.go @@ -45,7 +45,7 @@ type txsync struct { // syncTransactions starts sending all currently pending transactions to the given peer. func (pm *ProtocolManager) syncTransactions(p *peer) { var txs types.Transactions - pending, _ := pm.txpool.Pending() + pending, _ := pm.txpool.Pending(false) for _, batch := range pending { txs = append(txs, batch...) } diff --git a/miner/worker.go b/miner/worker.go index 3cd8fae940..c076518a60 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -616,7 +616,7 @@ func (w *worker) commitNewWork() { Time: big.NewInt(tstamp), } // Set baseFee if we are on an EIP-1559 chain - header.BaseFee = misc.CalcBaseFee(self.config, header) + header.BaseFee = misc.CalcBaseFee(w.config, header) // Only set the coinbase if we are mining (avoid spurious block rewards) if atomic.LoadInt32(&w.mining) == 1 { @@ -679,7 +679,7 @@ func (w *worker) commitNewWork() { log.Error("[commitNewWork] fail to check if block is epoch switch block when fetching pending transactions", "BlockNum", header.Number, "Hash", header.Hash()) } if !isEpochSwitchBlock { - pending, err := w.eth.TxPool().Pending() + pending, err := w.eth.TxPool().Pending(true) if err != nil { log.Error("Failed to fetch pending transactions", "err", err) return