From 9f5b620f8f9d6863526ded4d8677d32e35e1875e Mon Sep 17 00:00:00 2001 From: Mark Date: Tue, 13 Jul 2021 18:40:58 +0800 Subject: [PATCH] internal: get pending and queued transaction by address (#22992) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * core, eth, internal, les, light: get pending and queued transaction by address * core: tiny nitpick fixes * light: tiny nitpick Co-authored-by: mark Co-authored-by: Péter Szilágyi --- 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 a583c3d53527..c5b6047486e9 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -494,6 +494,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 37c5d8a09f00..f22462c7c88a 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -267,6 +267,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) TxPool() *core.TxPool { return b.eth.TxPool() } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index feb7b99fc23b..b65f98836c31 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -175,6 +175,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 90cfa852afd9..fe55ec59c82a 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -77,6 +77,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 // Filter API diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 9f9b2ba35e53..ba1324cf59ea 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -810,6 +810,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 2081ef64b1dd..2a2d406d1fee 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -219,6 +219,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) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { return b.eth.txPool.SubscribeNewTxsEvent(ch) } diff --git a/light/txpool.go b/light/txpool.go index 1296389e3b11..a7df4aeec388 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -505,6 +505,25 @@ 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() + + // 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 (pool *TxPool) RemoveTransactions(txs types.Transactions) { pool.mu.Lock()