Skip to content

fix mempool count overflow#2398

Open
Oscar-Pepper wants to merge 3 commits into
zingolabs:stablefrom
Oscar-Pepper:fix_mempool_count_overflow
Open

fix mempool count overflow#2398
Oscar-Pepper wants to merge 3 commits into
zingolabs:stablefrom
Oscar-Pepper:fix_mempool_count_overflow

Conversation

@Oscar-Pepper

Copy link
Copy Markdown
Contributor

Fixes: #2397

changed AtomicU8 to AtomicU32 to avoid overflow in the case of high volume of mempool txs

@Oscar-Pepper Oscar-Pepper added TOP PRIORITY This is the author's TOP priority, please consider first. least-authority audit issue detected by least authority audit labels Jun 12, 2026
dorianvp
dorianvp previously approved these changes Jun 12, 2026

@dorianvp dorianvp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

@dorianvp

Copy link
Copy Markdown
Member

According to an LLM (I know uhhg), this is a fix to a symptom of a larger problem:

Since the sender blocks when the channel is full, the legitimate steady-state count is bounded at ~101 — comfortably inside u8. "High volume of mempool txs" alone cannot overflow a u8 here.

According to it, the part that does underflow is:

let _ignore_error = mempool_transaction_sender.send(raw_transaction).await;
unprocessed_transactions_count.fetch_add(1, atomic::Ordering::Release);

If the receiver side is gone, send fails instantly, the error is swallowed, and the counter increments forever with no matching decrements. That's the unbounded growth, and widening to u32 just moves the wrap from 256 increments to 4 billion. The correct fix is to only increment when send returns Ok

@Oscar-Pepper

Oscar-Pepper commented Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

According to an LLM (I know uhhg), this is a fix to a symptom of a larger problem:

Since the sender blocks when the channel is full, the legitimate steady-state count is bounded at ~101 — comfortably inside u8. "High volume of mempool txs" alone cannot overflow a u8 here.

According to it, the part that does underflow is:

let _ignore_error = mempool_transaction_sender.send(raw_transaction).await;
unprocessed_transactions_count.fetch_add(1, atomic::Ordering::Release);

If the receiver side is gone, send fails instantly, the error is swallowed, and the counter increments forever with no matching decrements. That's the unbounded growth, and widening to u32 just moves the wrap from 256 increments to 4 billion. The correct fix is to only increment when send returns Ok

ok good point. so in practice this error can't be hit unless the whole sync fn has already been exited so it wouldnt matter, but i have added some extra precautions to avoid this wrapping in the case of the architecture changing in the future maybe allowing the mempool receiver to be dropped in some edge cases. i have kept the AtomicU32 for mempool count for similar reasons.. maybe in the future the mempool channel limit is raised beyond 256 risking overflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

least-authority audit issue detected by least authority audit TOP PRIORITY This is the author's TOP priority, please consider first.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants