diff --git a/core/txpool/locals/tx_tracker.go b/core/txpool/locals/tx_tracker.go index eccdcf422ad2..94cd2d7467f3 100644 --- a/core/txpool/locals/tx_tracker.go +++ b/core/txpool/locals/tx_tracker.go @@ -58,7 +58,7 @@ type TxTracker struct { // New creates a new TxTracker func New(journalPath string, journalTime time.Duration, chainConfig *params.ChainConfig, next *txpool.TxPool) *TxTracker { - pool := &TxTracker{ + tracker := &TxTracker{ all: make(map[common.Hash]*types.Transaction), byAddr: make(map[common.Address]*legacypool.SortedMap), signer: types.LatestSigner(chainConfig), @@ -66,10 +66,15 @@ func New(journalPath string, journalTime time.Duration, chainConfig *params.Chai pool: next, } if journalPath != "" { - pool.journal = newTxJournal(journalPath) - pool.rejournal = journalTime + tracker.journal = newTxJournal(journalPath) + tracker.rejournal = journalTime } - return pool + return tracker +} + +// HasTx checks if TxTracker has this tx already. +func (tracker *TxTracker) HasTx(hash common.Hash) bool { + return tracker.all[hash] != nil } // Track adds a transaction to the tracked set. diff --git a/eth/api_backend.go b/eth/api_backend.go index c8c5ca707f94..ee336d55003d 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -19,6 +19,7 @@ package eth import ( "context" "errors" + "github.com/ethereum/go-ethereum/log" "math/big" "time" @@ -274,18 +275,23 @@ func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscri func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { locals := b.eth.localTxTracker if locals != nil { + // If tx tracker already has the tx, that indicates + // the transaction has been submitted once. + // So local tracker should make sure the transaction + // submitted in the end. Just return nil error to inform + // the rpc client that tx has been received. + if locals.HasTx(signedTx.Hash()) { + log.Trace("Tx tracker has transaction and no need to add it to tx-pool", "hash", signedTx.Hash().Hex()) + return nil + } + // Transaction won't be tracked if tracker already has it if err := locals.Track(signedTx); err != nil { return err } } - // No error will be returned to user if the transaction fails stateful - // validation (e.g., no available slot), as the locally submitted transactions - // may be resubmitted later via the local tracker. - err := b.eth.txPool.Add([]*types.Transaction{signedTx}, false)[0] - if err != nil && locals == nil { - return err - } - return nil + // The rpc client needs to be informed if there is + // stateful validation problems. + return b.eth.txPool.Add([]*types.Transaction{signedTx}, false)[0] } func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {