From c49e065fea78a5d3759f7853a608494913e5824e 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 a583c3d53..c5b604748 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 37c5d8a09..f22462c7c 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 feb7b99fc..b65f98836 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 90cfa852a..fe55ec59c 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 9f9b2ba35..ba1324cf5 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 2081ef64b..2a2d406d1 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 1296389e3..a7df4aeec 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()