diff --git a/core/tx_pool.go b/core/tx_pool.go index 359db728456f..0d910f594c83 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 3a3766c26cbf..45b615689035 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 3c26e4fd5418..5b785a69da87 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 c0ccecca7c00..cd5a31ab5652 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -301,7 +301,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 4963093c1aa0..de175bbcee3d 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 eb7297a28c10..3876133e830e 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 cbe6d421c8bb..76edb614fbdb 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 0f5bf7e2a4a3..838d028ab05a 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -679,7 +679,7 @@ func (self *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 := self.eth.TxPool().Pending() + pending, err := self.eth.TxPool().Pending(true) if err != nil { log.Error("Failed to fetch pending transactions", "err", err) return