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 b0beead8c548..7de897a1befc 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 7812c88856e4..0209d6ce644f 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 47da23ef1d8a..8aaa3e9d263f 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -1081,6 +1081,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()