Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions pkg/transaction/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import (
var ErrTransactionCancelled = errors.New("transaction cancelled")
var ErrMonitorClosed = errors.New("monitor closed")

// MaxBlocksToWait is the maximum number of blocks to wait before considering a missing transaction as cancelled.
const MaxBlocksToWait = 5

// Monitor is a nonce-based watcher for transaction confirmations.
// Instead of watching transactions individually, the senders nonce is monitored and transactions are checked based on this.
// The idea is that if the nonce is still lower than that of a pending transaction, there is no point in actually checking the transaction for a receipt.
Expand Down Expand Up @@ -199,10 +202,11 @@ func (tm *transactionMonitor) checkPending(block uint64) error {
receipt, err := tm.backend.TransactionReceipt(tm.ctx, txHash)
if err != nil {
// wait for a few blocks to be mined before considering a transaction not existing
transactionWatchNotFoundTimeout := 5 * tm.pollingInterval
if errors.Is(err, ethereum.NotFound) && watchStart(watches).Before(time.Now().Add(transactionWatchNotFoundTimeout)) {
// if both err and receipt are nil, there is no receipt
// the reason why we consider this only potentially cancelled is to catch cases where after a reorg the original transaction wins
transactionWatchNotFoundTimeout := MaxBlocksToWait * tm.pollingInterval
if errors.Is(err, ethereum.NotFound) {
if watchStart(watches).Add(transactionWatchNotFoundTimeout).Before(time.Now()) {
cancelledNonces = append(cancelledNonces, nonceGroup)
}
continue
}
return err
Expand Down
37 changes: 37 additions & 0 deletions pkg/transaction/monitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,4 +388,41 @@ func TestMonitorWatchTransaction(t *testing.T) {
}
})

t.Run("missing transaction", func(t *testing.T) {
t.Parallel()
var blocks []backendsimulation.Block
for i := range transaction.MaxBlocksToWait + 1 {
blocks = append(blocks, backendsimulation.Block{Number: uint64(i)})
}
monitor := transaction.NewMonitor(
logger,
backendsimulation.New(
backendsimulation.WithBlocks(blocks...),
),
sender,
pollingInterval,
cancellationDepth,
)

receiptC, errC, err := monitor.WatchTransaction(txHash, nonce)
if err != nil {
t.Fatal(err)
}

select {
case <-receiptC:
t.Fatal("got receipt")
case err := <-errC:
if !errors.Is(err, transaction.ErrTransactionCancelled) {
t.Fatalf("got wrong error. wanted %v, got %v", transaction.ErrTransactionCancelled, err)
}
case <-time.After(testTimeout):
t.Fatal("timed out")
}

err = monitor.Close()
if err != nil {
t.Fatal(err)
}
})
}
Loading