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 1 month ago

To fix this issue, always check and handle errors returned by replacement.Close(). In this code, there are two places where replacement.Close() is called:

  • In the error path inside the loop, after a failed rlp.Encode
  • After the loop, when all transactions have been written

In both cases, the error from Close() should be checked. In the error path, if rlp.Encode fails, and replacement.Close() also fails, both errors are relevant, but returning the first error (the encoding error) is conventionally favored, though logging the close error could also be considered. In the success path, if replacement.Close() fails, its error should be returned to the caller instead of pretending everything succeeded.

The code should be updated to:

  • Check the error from replacement.Close().
  • In the error path, attempt to close and return the error from rlp.Encode (possibly logging any close error).
  • In the normal path, after replacement.Close(), return any error from closing (if present).

No extra imports or new methods are needed, just additional error handling.


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,13 +147,18 @@
 	for _, txs := range all {
 		for _, tx := range txs {
 			if err = rlp.Encode(replacement, tx); err != nil {
-				replacement.Close()
+				closeErr := replacement.Close()
+				if closeErr != nil {
+					// Optionally, log closeErr here using `log.Warn`, since only one error can be returned.
+				}
 				return err
 			}
 		}
 		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
@@ -147,13 +147,18 @@
for _, txs := range all {
for _, tx := range txs {
if err = rlp.Encode(replacement, tx); err != nil {
replacement.Close()
closeErr := replacement.Close()
if closeErr != nil {
// Optionally, log closeErr here using `log.Warn`, since only one error can be returned.
}
return err
}
}
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.
}
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 1 month ago

General approach:
Explicitly check the error returned by replacement.Close() on line 156, and propagate it up by returning if it is non-nil.

Detailed steps:

  • After the loop writing to replacement, instead of calling replacement.Close() and discarding its error, check it.
  • If this error is non-nil, return it immediately, just as is done for other errors within rotate.
  • This preserves the existing functional behavior but closes the bug where a late error would be suppressed.
  • No additional imports or helpers are needed. Just update the close call and error handling.

Where to change:

  • In mempool/txpool/locals/journal.go, in the rotate function, around line 156 (after writing transactions and before renaming the file).

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
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