Skip to content

Conversation

@vladjdk
Copy link
Member

@vladjdk vladjdk commented Sep 22, 2025

Description

Closes: #500


Author Checklist

I have...

  • tackled an existing issue or discussed with a team member
  • left instructions on how to review the changes
  • targeted the main branch

Comment on lines +147 to +155
for _, txs := range all {
for _, tx := range txs {
if err = rlp.Encode(replacement, tx); err != nil {
replacement.Close()
return err
}
}
journaled += len(txs)
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
for _, txs := range all {
for _, tx := range txs {
if err = rlp.Encode(replacement, tx); err != nil {
replacement.Close()

Check warning

Code scanning / CodeQL

Writable file handle closed without error handling Warning

File handle may be writable as a result of data flow from a
call to OpenFile
and closing it may result in data loss upon failure, which is not handled explicitly.

Copilot Autofix

AI about 2 hours ago

To fix the problem, we must ensure that any error returned by replacement.Close() is neither ignored nor silently discarded. Specifically, in the event that a write (rlp.Encode) fails inside the loop, the code should close the file and capture any error from Close(). If Close() also fails, both errors should be reported—ideally by combining them. The canonical way in Go is to chain or wrap the Close error with the initial error (if both occur). This can be done with Go's errors.Join (Go 1.20+) or, for older Go, by concatenating the messages or using a helper function. Since the import errors is already present, and Go 1.20+'s errors.Join is standard, I'll use that.

The fix consists of:

  • Not just calling replacement.Close() without checking, but capturing its error.
  • If both rlp.Encode and replacement.Close error, return errors.Join(encodeErr, closeErr).
  • If only one errors, return that error.
  • Changing only the relevant region of the file in the shown snippet (mempool/txpool/locals/journal.go).

Suggested changeset 1
mempool/txpool/locals/journal.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/mempool/txpool/locals/journal.go b/mempool/txpool/locals/journal.go
--- a/mempool/txpool/locals/journal.go
+++ b/mempool/txpool/locals/journal.go
@@ -147,7 +147,10 @@
 	for _, txs := range all {
 		for _, tx := range txs {
 			if err = rlp.Encode(replacement, tx); err != nil {
-				replacement.Close()
+				closeErr := replacement.Close()
+				if closeErr != nil {
+					return errors.Join(err, closeErr)
+				}
 				return err
 			}
 		}
EOF
@@ -147,7 +147,10 @@
for _, txs := range all {
for _, tx := range txs {
if err = rlp.Encode(replacement, tx); err != nil {
replacement.Close()
closeErr := replacement.Close()
if closeErr != nil {
return errors.Join(err, closeErr)
}
return err
}
}
Copilot is powered by AI and may make mistakes. Always verify output.
}
journaled += len(txs)
}
replacement.Close()

Check warning

Code scanning / CodeQL

Writable file handle closed without error handling Warning

File handle may be writable as a result of data flow from a
call to OpenFile
and closing it may result in data loss upon failure, which is not handled explicitly.

Copilot Autofix

AI about 2 hours ago

To fix the problem, always check the error result returned by replacement.Close() (line 156) and handle it as you do for other file operations in the same function. The best way, patterned after the rest of the function, is to assign the error returned from replacement.Close() to err, and if it is non-nil, return it as the function error immediately. This ensures that any issue closing the file is surfaced and handled, avoiding silent data loss.

Changes needed:

  • In mempool/txpool/locals/journal.go, in the rotate method, replace the call at line 156 from replacement.Close() to:
    if err = replacement.Close(); err != nil {
        return err
    }

No new imports or method definitions are necessary, as this is the pattern for error handling already used in this function.

Suggested changeset 1
mempool/txpool/locals/journal.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/mempool/txpool/locals/journal.go b/mempool/txpool/locals/journal.go
--- a/mempool/txpool/locals/journal.go
+++ b/mempool/txpool/locals/journal.go
@@ -153,7 +153,9 @@
 		}
 		journaled += len(txs)
 	}
-	replacement.Close()
+	if err = replacement.Close(); err != nil {
+		return err
+	}
 
 	// Replace the live journal with the newly generated one
 	if err = os.Rename(journal.path+".new", journal.path); err != nil {
EOF
@@ -153,7 +153,9 @@
}
journaled += len(txs)
}
replacement.Close()
if err = replacement.Close(); err != nil {
return err
}

// Replace the live journal with the newly generated one
if err = os.Rename(journal.path+".new", journal.path); err != nil {
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +125 to +141
for sender, txs := range tracker.byAddr {
// Wipe the stales
stales := txs.Forward(tracker.pool.Nonce(sender))
for _, tx := range stales {
delete(tracker.all, tx.Hash())
}
numStales += len(stales)

// Check the non-stale
for _, tx := range txs.Flatten() {
if tracker.pool.Has(tx.Hash()) {
numOk++
continue
}
resubmits = append(resubmits, tx)
}
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +145 to +148
for _, tx := range tracker.all {
addr, _ := types.Sender(tracker.signer, tx)
rejournal[addr] = append(rejournal[addr], tx)
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
Comment on lines +150 to +155
for _, list := range rejournal {
// cmp(a, b) should return a negative number when a < b,
slices.SortFunc(list, func(a, b *types.Transaction) int {
return int(a.Nonce() - b.Nonce())
})
}

Check warning

Code scanning / CodeQL

Iteration over map Warning

Iteration over map may be a possible source of non-determinism
// layer was also initialized to spawn any goroutines required by the service.
func (tracker *TxTracker) Start() error {
tracker.wg.Add(1)
go tracker.loop()

Check notice

Code scanning / CodeQL

Spawning a Go routine Note

Spawning a Go routine may be a possible source of non-determinism
defer tracker.journal.close()
}
var (
lastJournal = time.Now()

Check warning

Code scanning / CodeQL

Calling the system time Warning

Calling the system time may be a possible source of non-determinism
if checkJournal {
// Lock to prevent journal.rotate <-> journal.insert (via TrackAll) conflicts
tracker.mu.Lock()
lastJournal = time.Now()

Check warning

Code scanning / CodeQL

Calling the system time Warning

Calling the system time may be a possible source of non-determinism
@almk-dev almk-dev changed the title wip: set up local journal feat(mempool): Add TxTracker support for handling temporary rejections Oct 24, 2025
@almk-dev almk-dev changed the title feat(mempool): Add TxTracker support for handling temporary rejections feat(mempool): Add TxTracker support for handling temporary rejections Oct 24, 2025
@almk-dev almk-dev marked this pull request as ready for review October 27, 2025 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat]: support TxTracker to track priority transactions

2 participants