From 483a893e18f46f92c719c4683bebb2f6e6083f16 Mon Sep 17 00:00:00 2001 From: Daniel Liu Date: Wed, 29 May 2024 14:18:20 +0800 Subject: [PATCH] internal: get pending and queued transaction by address (#22992) --- core/tx_pool.go | 17 +++++++++++++++++ eth/api_backend.go | 4 ++++ internal/ethapi/api.go | 23 +++++++++++++++++++++++ internal/ethapi/backend.go | 1 + internal/web3ext/web3ext.go | 5 +++++ les/api_backend.go | 4 ++++ light/txpool.go | 19 +++++++++++++++++++ 7 files changed, 73 insertions(+) diff --git a/core/tx_pool.go b/core/tx_pool.go index 9c7f3f7dbc09..7162dd778c4e 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -535,6 +535,23 @@ func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common return pending, queued } +// ContentFrom retrieves the data content of the transaction pool, returning the +// pending as well as queued transactions of this address, grouped by nonce. +func (pool *TxPool) ContentFrom(addr common.Address) (types.Transactions, types.Transactions) { + pool.mu.RLock() + defer pool.mu.RUnlock() + + var pending types.Transactions + if list, ok := pool.pending[addr]; ok { + pending = list.Flatten() + } + var queued types.Transactions + if list, ok := pool.queue[addr]; ok { + queued = list.Flatten() + } + return pending, queued +} + // 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. diff --git a/eth/api_backend.go b/eth/api_backend.go index 7ebd32e73dbf..48fc74b2354b 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -325,6 +325,10 @@ func (b *EthApiBackend) TxPoolContent() (map[common.Address]types.Transactions, return b.eth.TxPool().Content() } +func (b *EthApiBackend) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) { + return b.eth.TxPool().ContentFrom(addr) +} + func (b *EthApiBackend) OrderTxPoolContent() (map[common.Address]types.OrderTransactions, map[common.Address]types.OrderTransactions) { return b.eth.OrderPool().Content() } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index da23aee4a795..11255aae64c6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -202,6 +202,29 @@ func (s *PublicTxPoolAPI) Content() map[string]map[string]map[string]*RPCTransac return content } +// ContentFrom returns the transactions contained within the transaction pool. +func (s *PublicTxPoolAPI) ContentFrom(addr common.Address) map[string]map[string]*RPCTransaction { + content := make(map[string]map[string]*RPCTransaction, 2) + pending, queue := s.b.TxPoolContentFrom(addr) + curHeader := s.b.CurrentHeader() + + // Build the pending transactions + dump := make(map[string]*RPCTransaction, len(pending)) + for _, tx := range pending { + dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()) + } + content["pending"] = dump + + // Build the queued transactions + dump = make(map[string]*RPCTransaction, len(queue)) + for _, tx := range queue { + dump[fmt.Sprintf("%d", tx.Nonce())] = newRPCPendingTransaction(tx, curHeader, s.b.ChainConfig()) + } + content["queued"] = dump + + return content +} + // Status returns the number of pending and queued transaction in the pool. func (s *PublicTxPoolAPI) Status() map[string]hexutil.Uint { pending, queue := s.b.Stats() diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index a773c0033536..6b66806ebf28 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -84,6 +84,7 @@ type Backend interface { GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) Stats() (pending int, queued int) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) + TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription // Order Pool Transaction diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index ab4c8d70e259..5c8f88aa7cdf 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -1071,6 +1071,11 @@ web3._extend({ return status; } }), + new web3._extend.Method({ + name: 'contentFrom', + call: 'txpool_contentFrom', + params: 1, + }), ] }); ` diff --git a/les/api_backend.go b/les/api_backend.go index 3a4dd191f7b4..59c2c474331b 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -226,6 +226,10 @@ func (b *LesApiBackend) TxPoolContent() (map[common.Address]types.Transactions, return b.eth.txPool.Content() } +func (b *LesApiBackend) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) { + return b.eth.txPool.ContentFrom(addr) +} + func (b *LesApiBackend) OrderTxPoolContent() (map[common.Address]types.OrderTransactions, map[common.Address]types.OrderTransactions) { return make(map[common.Address]types.OrderTransactions), make(map[common.Address]types.OrderTransactions) } diff --git a/light/txpool.go b/light/txpool.go index 92e42101a733..d9566e2a7076 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -530,6 +530,25 @@ func (p *TxPool) Content() (map[common.Address]types.Transactions, map[common.Ad return pending, queued } +// ContentFrom retrieves the data content of the transaction pool, returning the +// pending as well as queued transactions of this address, grouped by nonce. +func (pool *TxPool) ContentFrom(addr common.Address) (types.Transactions, types.Transactions) { + pool.mu.RLock() + defer pool.mu.RUnlock() + + // Retrieve the pending transactions and sort by nonce + var pending types.Transactions + for _, tx := range pool.pending { + account, _ := types.Sender(pool.signer, tx) + if account != addr { + continue + } + pending = append(pending, tx) + } + // There are no queued transactions in a light pool, just return an empty map + return pending, types.Transactions{} +} + // RemoveTransactions removes all given transactions from the pool. func (p *TxPool) RemoveTransactions(txs types.Transactions) { p.mu.Lock()