Skip to content

Conversation

@m2ux
Copy link
Contributor

@m2ux m2ux commented Dec 12, 2025

Summary

Add pre-dispatch validation to prevent transactions whose guaranteed part will fail from being included in blocks, closing a DDoS attack vector where attackers can fill blocks without paying fees.

🎫 Ticket 📐 ADR 🧪 Test Plan


Motivation

Midnight transactions have a two-phase execution model where the guaranteed part always executes (and extracts fees) while the fallible part may succeed or fail. A DDoS vulnerability exists where transactions can pass structural validation (well_formed()) but fail during guaranteed execution—consuming blockspace without paying fees.

An attacker can exploit this by flooding the network with structurally valid transactions designed to fail the guaranteed part (e.g., calling non-existent contracts, replaying transactions), filling blocks at zero cost and denying service to legitimate users.


Changes

  • Ledger - Add validate_guaranteed_execution() to simulate guaranteed part execution without modifying state
  • Bridge/Host API - Expose validate_guaranteed_execution through the Bridge API and host functions
  • Midnight Pallet - Enhance pre_dispatch hook to call validation before block inclusion
  • Tests - Unit tests for all rejection vectors; E2E tests for attack simulation

📌 Submission Checklist

  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason: Change file added
  • If the changes introduce a new feature, I have bumped the node minor version
  • Update documentation (if relevant)
  • No new todos introduced

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other
  • N/A

🗹 TODO before merging

  • Ready for review

Add architecture decision record documenting the approach to prevent
DDoS attacks where failed transactions consume blockspace without
paying fees.

Ticket: PM-20944
@m2ux m2ux requested a review from a team as a code owner December 12, 2025 17:41
@github-actions
Copy link
Contributor

github-actions bot commented Dec 12, 2025

Logo
Checkmarx One – Scan Summary & Detailsa4a8be03-cc31-47bb-bd0e-9f1dd61ebcb9

Great job! No new security vulnerabilities introduced in this pull request

Add validation in pre_dispatch to detect and reject transactions
whose guaranteed part would fail before they are included in blocks.

This prevents a DDoS attack vector where attackers could fill blocks
with transactions that fail the guaranteed phase (before fees are
extracted), consuming blockspace without paying fees.

Changes:
- Add Ledger::validate_guaranteed_execution() for dry-run validation
- Add Bridge::validate_guaranteed_execution() method
- Add host API function for validate_guaranteed_execution
- Enhance pre_dispatch to call guaranteed validation

The validation performs a dry-run of the transaction application
to detect TransactionResult::Failure without persisting any state
changes. Transactions that would fail are rejected with
InvalidTransaction error.

Ticket: PM-20944
@m2ux m2ux self-assigned this Dec 12, 2025
@m2ux m2ux marked this pull request as draft December 12, 2025 17:58
m2ux and others added 24 commits December 12, 2025 18:27
Add required feature flags to dev-dependencies:
- midnight-node-ledger-helpers: add 'can-panic' for extract_info_from_tx_with_context
- midnight-node-ledger: add 'std' and 'test-utils' for BlockContext conversion

This fixes pre-existing test infrastructure issues that prevented
pallet tests from compiling.
Add unit tests to verify the DDoS mitigation works correctly:
- test_pre_dispatch_accepts_valid_transaction: valid tx passes
- test_pre_dispatch_rejects_contract_not_present: tx calling missing contract rejected
- test_pre_dispatch_rejects_malformed_transaction: malformed tx rejected

These tests verify that transactions which would fail the guaranteed
part are rejected at pre_dispatch time, preventing blockspace consumption
without fee payment.

Ticket: PM-20944
- TC-0003-02: test_pre_dispatch_rejects_replay_attack
- TC-0003-05: test_pre_dispatch_validation_does_not_modify_state
- TC-0003-05: test_pre_dispatch_validation_does_not_modify_state_on_failure

All 16 pallet unit tests passing.
@m2ux m2ux added ci:arm64 and removed ci:arm64 labels Dec 17, 2025
m2ux and others added 10 commits December 17, 2025 15:41
- ADR-0003: Convert to standard template structure with proper Status
  section, Context with force subsections, consolidated Decision section,
  and Confirmation criteria
- Test Plan: Convert to table format with hyperlinked Test IDs and
  symbols, remove redundant sections, add Running Tests commands
Remove suffixes (b, e2e) and ADR number from test IDs.
Now uses simple PR367-TC-01 through PR367-TC-08 format.
…ution

Address PR review comment explaining that while validate_unsigned() already
performs well_formed() validation, we must call it again here because:
- apply() requires a VerifiedTransaction type
- The earlier validation discards that result
- This is a type-system constraint, not redundant logic
- docs/decisions/0003-prevent-feeless-blockspace-ddos.md -> docs/architecture/adr-prevent-feeless-blockspace-ddos.md
- docs/tests/0003-prevent-feeless-blockspace-ddos.md -> docs/tests/test-plan-prevent-feeless-blockspace-ddos.md
@m2ux m2ux requested a review from justinfrevert December 18, 2025 17:07
m2ux added 3 commits December 21, 2025 18:14
- Add replay_attack_rejected_via_rpc E2E test
- Verifies duplicate transaction submission is rejected at pre_dispatch
- Complements existing DDoS mitigation tests (TC-0003-06)

WP: Prevent Feeless Blockspace DDoS
@m2ux m2ux requested a review from justinfrevert December 29, 2025 15:45
@m2ux m2ux force-pushed the fix/prevent-feeless-blockspace-ddos branch from 7718448 to b9f4be3 Compare January 6, 2026 17:18
@m2ux m2ux enabled auto-merge (squash) January 6, 2026 18:28
@m2ux m2ux merged commit 9c4e485 into main Jan 6, 2026
36 checks passed
@m2ux m2ux deleted the fix/prevent-feeless-blockspace-ddos branch January 6, 2026 19:29
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.

3 participants