Skip to content

fix: evict balance-failing transactions from mempool at admission and mining time#122

Closed
g-k-s-03 wants to merge 2 commits into
StabilityNexus:mainfrom
g-k-s-03:fix/mempool-balance-eviction
Closed

fix: evict balance-failing transactions from mempool at admission and mining time#122
g-k-s-03 wants to merge 2 commits into
StabilityNexus:mainfrom
g-k-s-03:fix/mempool-balance-eviction

Conversation

@g-k-s-03

@g-k-s-03 g-k-s-03 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Addressed Issues: Fixes #121

summary
Transactions that passed signature verification but failed balance checks during mining were never evicted from the mempool. This allowed an attacker with zero funds to permanently fill the mempool with validly signed but unfunded transactions at no cost, blocking all future legitimate transactions.

What Was Fixed

  1. Balance check at admission time (mempool.py)
    Added an optional state_provider callable to Mempool.init(). When configured, add_transaction() now rejects transactions whose sender cannot afford amount + fee immediately at admission time, before they ever enter the mempool. If no state_provider is configured, the mempool falls back to signature-only admission, preserving backward compatibility.
  2. Explicit eviction during mining (main.py)
    mine_and_process_block() now explicitly tracks transactions that are permanently stuck (nonce matches but balance is insufficient) and evicts them after each mining cycle instead of silently skipping them. Higher-nonce transactions are left in the mempool for future cycles as before.
  3. Mempool wired to live chain state (main.py)
    Mempool is now instantiated with state_provider=lambda: chain.state so it always observes the latest state, even after chain reorganizations or block mining replace the state wholesale.

Testing
Two new tests added to tests/test_core.py:

test_mempool_rejects_unfunded_transaction — confirms balance-failing transactions are rejected at admission
test_unminable_transaction_evicted_during_mining — confirms stuck transactions are evicted during a mining cycle

py -3.11 -m pytest tests/ -v
76 passed, 0 failed

Summary by CodeRabbit

  • Bug Fixes
    • Transactions now require sufficient balance before entering the mempool, reducing failed submissions later in processing.
    • Mining now removes transactions that can’t be executed and only includes valid ones in receipts and fee totals.
    • Transactions with past nonces are cleaned up more reliably, while future-nonce transactions remain queued.
  • Tests
    • Added coverage for rejected low-balance transactions and for eviction of unexecutable transactions during mining.

… mining time

Signed-off-by: g-k-s-03 <govindsingh97704@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@g-k-s-03, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0b1ac8a9-8af1-4096-9e12-c8b738d2f67e

📥 Commits

Reviewing files that changed from the base of the PR and between 8b12f12 and 699cca4.

📒 Files selected for processing (1)
  • minichain/mempool.py

Walkthrough

Mempool now supports an optional state_provider used to validate sender balance at admission time via _sender_can_afford, rejecting unaffordable transactions. mine_and_process_block was refactored to classify queued transactions by nonce and validation status, evicting stale/rejected ones and deriving receipts/fees only from valid transactions. run_node wires the mempool to chain state. Tests cover both rejection and mining-time eviction.

Changes

Mempool DoS fix

Layer / File(s) Summary
Mempool balance check on admission
minichain/mempool.py
Adds optional state_provider to Mempool.__init__ and a new _sender_can_afford method used by add_transaction to reject transactions when the sender's balance can't cover amount + fee.
Mining-time nonce/status-based eviction
main.py
Refactors mine_and_process_block to classify queued mempool transactions by nonce (stale, rejected, future), use validate_and_apply_with_status, evict stale/rejected transactions, and derive receipts/fees only from VALID transactions; run_node now builds Mempool with state_provider=lambda: chain.state.
Tests for rejection and mining eviction
tests/test_core.py
Adds tests verifying immediate rejection of unfunded transactions with a state_provider and eviction of unfundable transactions during mining.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • StabilityNexus/MiniChain#89: Both PRs modify main.py's mine_and_process_block mining-candidate selection logic around validating/applying transactions and handling stale/evicted nonce cases.
  • StabilityNexus/MiniChain#107: Both rely on validate_and_apply_with_status/ValidationStatus.VALID for transaction selection and fee accounting in mine_and_process_block.
  • StabilityNexus/MiniChain#60: Both modify the block-minting flow to identify mineable vs stale/unexecutable transactions and evict stale ones during mining.

Suggested labels: Python Lang

Suggested reviewers: Zahnentferner

Poem

A rabbit checks each purse and pouch,
No empty wallet gets to vouch,
Stale nonces swept, rejects set free,
The mempool hums with honesty,
Hop hop, secure as it can be! 🐇💰

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the main behavior change: evicting unfunded transactions at admission and during mining.
Linked Issues check ✅ Passed The changes satisfy #121 by rejecting unfunded transactions on admission and evicting balance-failing ones during block construction.
Out of Scope Changes check ✅ Passed No unrelated code changes stand out beyond the mempool admission, mining, and test updates required by the issue.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@minichain/mempool.py`:
- Line 3: Ruff flagged two small style issues in the mempool module: the import
of Callable should come from collections.abc instead of typing, and __init__ is
missing an explicit -> None return annotation. Update the imports in mempool.py
accordingly, and add the None return annotation to the __init__ method (and the
other affected __init__ at the referenced location) while keeping the existing
TYPE_CHECKING and Optional usage unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 05baf8db-4346-4fe2-bc5e-c70330e31e8a

📥 Commits

Reviewing files that changed from the base of the PR and between 9419fdb and 8b12f12.

📒 Files selected for processing (3)
  • main.py
  • minichain/mempool.py
  • tests/test_core.py

Comment thread minichain/mempool.py Outdated
Signed-off-by: g-k-s-03 <govindsingh97704@gmail.com>
@g-k-s-03

g-k-s-03 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@g-k-s-03 g-k-s-03 closed this Jul 8, 2026
@g-k-s-03 g-k-s-03 deleted the fix/mempool-balance-eviction branch July 8, 2026 20:13
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.

fix: mempool never evicts balance-failing transactions enabling DoS

1 participant