diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 3947ba50a1..4144c3a1b2 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -1366,6 +1366,25 @@ func (p *BlobPool) GetMetadata(hash common.Hash) *txpool.TxMetadata { } } +// GetTxBySenderAndNonce returns a transaction of a sender and its corresponding nonce. +func (p *BlobPool) GetTxBySenderAndNonce(sender common.Address, nonce uint64) *types.Transaction { + p.lock.RLock() + defer p.lock.RUnlock() + + txs, ok := p.index[sender] + if !ok { + return nil + } + next := p.state.GetNonce(sender) + offset := int(nonce - next) + + if offset < 0 || offset >= len(txs) { + return nil + } + + return p.Get(txs[offset].hash) +} + // GetBlobs returns a number of blobs and proofs for the given versioned hashes. // Blobpool must place responses in the order given in the request, using null // for any missing blobs. diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 36970c820e..2287299a27 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -1035,6 +1035,25 @@ func (pool *LegacyPool) GetMetadata(hash common.Hash) *txpool.TxMetadata { } } +// GetTxBySenderAndNonce returns a transaction of a sender and it's corresponding nonce. +func (pool *LegacyPool) GetTxBySenderAndNonce(sender common.Address, nonce uint64) *types.Transaction { + // Check if the transaction is in the pending pool + if txList := pool.pending[sender]; txList != nil { + if tx := txList.txs.items[nonce]; tx != nil { + return tx + } + } + + // Check if the transaction is in the queue pool + if txList, ok := pool.queue.get(sender); ok { + if tx := txList.txs.items[nonce]; tx != nil { + return tx + } + } + + return nil +} + // Has returns an indicator whether txpool has a transaction cached with the // given hash. func (pool *LegacyPool) Has(hash common.Hash) bool { diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go index db099ddf98..b2e4d2b40d 100644 --- a/core/txpool/subpool.go +++ b/core/txpool/subpool.go @@ -138,6 +138,9 @@ type SubPool interface { // given transaction hash. GetMetadata(hash common.Hash) *TxMetadata + // GetTxBySenderAndNonce returns a transaction of a sender and it's corresponding nonce. + GetTxBySenderAndNonce(sender common.Address, nonce uint64) *types.Transaction + // ValidateTxBasics checks whether a transaction is valid according to the consensus // rules, but does not check state-dependent validation such as sufficient balance. // This check is meant as a static check which can be performed without holding the diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index a314a83f1b..94355abd70 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -305,6 +305,16 @@ func (p *TxPool) GetMetadata(hash common.Hash) *TxMetadata { return nil } +// GetTxBySenderAndNonce returns a transaction of a sender and it's corresponding nonce. +func (p *TxPool) GetTxBySenderAndNonce(sender common.Address, nonce uint64) *types.Transaction { + for _, subpool := range p.subpools { + if tx := subpool.GetTxBySenderAndNonce(sender, nonce); tx != nil { + return tx + } + } + return nil +} + // Add enqueues a batch of transactions into the pool if they are valid. Due // to the large transaction churn, add may postpone fully integrating the tx // to a later point to batch multiple ones together.