Skip to content

Conversation

@snissn
Copy link
Contributor

@snissn snissn commented Nov 18, 2025

feat: add engine‑managed tipset gas reservations to ref‑fvm

This PR implements engine‑managed tipset‑scope gas reservations inside ref‑fvm, as described in a pending FIP proposal.

Summary

  • Add a reservation session ledger on the default executor keyed by ActorID.
  • Implement begin_reservation_session / end_reservation_session with affordability checks and invariants.
  • Rewrite preflight to assert coverage without pre‑deducting gas funds in reservation mode.
  • Enforce transfers against free balance balance − reserved_remaining.
  • Rewrite settlement to net‑charge gas and realize refunds via reservation release.
  • Add reservation telemetry and tests (unit + integration).

Changes

Executor: session lifecycle and preflight

  • fvm/src/executor/mod.rs

    • Add:
      • ReservationSession struct (re‑exported from default.rs) and ReservationError enum:
        • NotImplemented
        • InsufficientFundsAtBegin { sender }
        • SessionOpen
        • SessionClosed
        • NonZeroRemainder
        • PlanTooLarge
        • Overflow
        • ReservationInvariant(String)
  • fvm/src/executor/default.rs

    • Add ReservationSession { reservations: HashMap<ActorID, TokenAmount>, open: bool } and an Arc<Mutex<_>> on DefaultExecutor.
    • Implement:
      • begin_reservation_session(&mut self, plan: &[(Address, TokenAmount)]) -> Result<(), ReservationError>:
        • Empty plan = no‑op (do not enter reservation mode).
        • Enforce MAX_SENDERS (65,536) and track plan failures via telemetry.
        • Resolve senders via the state tree (robust or ID addresses → ActorID).
        • Aggregate Σ(plan) per actor and enforce reserved_total <= balance per sender.
        • Enforce single active session.
      • end_reservation_session(&mut self) -> Result<(), ReservationError>:
        • Require open == true and all reservation entries to be zero.
        • Clear the ledger and close the session; update telemetry.
    • Preflight:
      • Compute gas_cost = gas_fee_cap * gas_limit using big‑int; treat negative results as ReservationError::Overflow.
      • In reservation mode:
        • Assert coverage via reservation_assert_coverage(sender, &gas_cost); do not pre‑deduct funds.
        • On prevalidation failures (invalid sender, bad nonce, inclusion gas > limit), call reservation_prevalidation_decrement so the ledger can end at zero.
      • Legacy mode:
        • Preserve existing behaviour (check balance ≥ gas_cost, pre‑deduct from sender).

Transfer enforcement and settlement

  • fvm/src/call_manager/default.rs & fvm/src/call_manager/mod.rs

    • Thread Arc<Mutex<ReservationSession>> into the default call manager.
    • In transfer(from, to, value):
      • When the reservation session is open:
        • Compute reserved_remaining = reservations.get(from).unwrap_or(0).
        • Enforce value + reserved_remaining <= from.balance; otherwise return InsufficientFunds.
      • When no session is open:
        • Preserve existing value <= balance semantics.
  • fvm/src/executor/default.rs

    • Settlement (finish_message) in reservation mode:
      • Compute GasOutputs as today.
      • Define consumption = base_fee_burn + over_estimation_burn + miner_tip.
      • Deduct consumption from the sender’s actor balance.
      • Deposit burns and tip to the existing reward/burn actors.
      • Do not deposit refund to the sender; the “refund effect” is realized by releasing the reservation ledger.
      • Decrement reservations[sender] by gas_cost using reservation_prevalidation_decrement, update telemetry, and remove entries at zero.
    • Legacy mode settlement is unchanged.
    • Preserve the invariant:
      • base_fee_burn + over_estimation_burn + refund + miner_tip == gas_cost.

Telemetry

  • fvm/src/executor/telemetry.rs
    • Add ReservationTelemetry and helpers:
      • Track:
        • reservations_open
        • reservation_begin_failed
        • settle_basefee_burn
        • settle_tip_credit
        • settle_overburn
        • settle_refund_virtual
        • Per‑sender reservation totals and remaining amounts.
    • Expose snapshot() (for potential host export) and reset() under #[cfg(test)].

Kernel and test harness adjustments

  • fvm/src/kernel/default.rs

    • Plumb the updated CallManager type where necessary so that all value‑moving operations (SendOps, SELFDESTRUCT, etc.) route through the reservation‑aware transfer.
  • fvm/tests/dummy.rs

    • Update the dummy CallManager impl to accept the new ReservationSession argument in CallManager::new, keeping tests compiling against the updated trait.

Tests

  • Unit tests in fvm/src/executor/default.rs:

    • Session lifecycle: empty plan, begin twice, end with non‑zero remainder, plan too large, unknown actors.
    • Preflight behaviour under reservations:
      • Coverage assertion, no balance deduction.
      • Under‑reserved ledger → ReservationError::Overflow.
    • Transfer enforcement:
      • transfer, send to existing actors, SELFDESTRUCT, and implicit sends must respect free balance.
    • Settlement invariants:
      • Net sender delta equals consumption.
      • Reservation ledger clears so end_reservation_session succeeds.
    • Gas output property test (with --features arb) continues to assert:
      • All components non‑negative.
      • base_fee_burn + over_estimation_burn + refund + miner_tip == gas_cost.
  • Integration tests:

    • testing/integration/tests/reservation_transfer_enforcement.rs:
      • Uses the integration tester to exercise reservation mode and confirm that:
        • Sends and actor creation fail when value > free = balance − reserved_remaining.
        • Failed transfers do not credit receivers.

Activation and host behaviour

  • ref‑fvm does not contain any network‑version logic for reservations.
  • Hosts (e.g., Lotus) control:
    • When to call begin_reservation_session / end_reservation_session.
    • How to treat ReservationError variants (legacy fallback, tipset invalid, node error) based on network version and feature flags.

Notes

  • This PR is designed to preserve receipts (ExitCode, GasUsed, events) and GasOutputs relative to pre‑reservation behaviour, while removing miner exposure to intra‑tipset underfunded messages when hosts enable reservations.

@snissn snissn self-assigned this Nov 18, 2025
@github-project-automation github-project-automation bot moved this to 📌 Triage in FilOz Nov 18, 2025
@snissn snissn force-pushed the multistage-execution branch from 770523f to 56c2695 Compare November 18, 2025 00:43
@snissn
Copy link
Contributor Author

snissn commented Nov 18, 2025

@codecov-commenter
Copy link

codecov-commenter commented Nov 20, 2025

Codecov Report

❌ Patch coverage is 89.09091% with 132 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.90%. Comparing base (71c2f8c) to head (fc0efc9).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
fvm/src/executor/default.rs 89.32% 121 Missing ⚠️
fvm/src/call_manager/default.rs 77.14% 8 Missing ⚠️
fvm/src/executor/telemetry.rs 91.42% 3 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2236      +/-   ##
==========================================
+ Coverage   77.58%   78.90%   +1.31%     
==========================================
  Files         147      148       +1     
  Lines       15789    16979    +1190     
==========================================
+ Hits        12250    13397    +1147     
- Misses       3539     3582      +43     
Files with missing lines Coverage Δ
fvm/src/call_manager/mod.rs 83.33% <ø> (ø)
fvm/src/executor/mod.rs 93.93% <ø> (+72.72%) ⬆️
fvm/src/kernel/default.rs 82.26% <100.00%> (+0.02%) ⬆️
fvm/src/executor/telemetry.rs 91.42% <91.42%> (ø)
fvm/src/call_manager/default.rs 89.53% <77.14%> (-0.52%) ⬇️
fvm/src/executor/default.rs 88.19% <89.32%> (+10.47%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@snissn snissn marked this pull request as ready for review November 20, 2025 22:30
Copilot AI review requested due to automatic review settings November 20, 2025 22:30
Copilot finished reviewing on behalf of snissn November 20, 2025 22:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements engine-managed tipset-scope gas reservations in ref-fvm to prevent miners from being exposed to intra-tipset underfunded messages. The implementation adds a reservation session ledger that tracks per-actor gas commitments throughout tipset execution, with settlement realizing refunds through reservation release rather than direct balance transfers.

Key changes:

  • Add ReservationSession ledger and lifecycle methods (begin_reservation_session/end_reservation_session) with affordability checks
  • Modify preflight to assert coverage without pre-deducting funds in reservation mode
  • Enforce transfer restrictions against free balance (balance - reserved_remaining)
  • Update settlement to net-charge gas costs and realize refunds via reservation release
  • Add reservation telemetry tracking and comprehensive test coverage

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
fvm/src/executor/mod.rs Defines ReservationError enum and re-exports ReservationSession struct for public API
fvm/src/executor/default.rs Core implementation of reservation session lifecycle, preflight validation, settlement logic, and extensive unit tests
fvm/src/executor/telemetry.rs New telemetry module for tracking reservation metrics using global singleton with per-sender gauges
fvm/src/call_manager/mod.rs Updates CallManager::new trait signature to accept ReservationSession parameter
fvm/src/call_manager/default.rs Implements reservation-aware transfer enforcement by checking free balance against reserved amounts
fvm/src/kernel/default.rs Minor formatting change to self-destruct error handling to route through reservation-aware transfer
fvm/tests/dummy.rs Updates dummy CallManager implementation to accept new ReservationSession argument
testing/integration/tests/reservation_transfer_enforcement.rs New integration tests verifying reservation enforcement for sends and actor creation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@BigLep BigLep requested a review from ZenGround0 December 1, 2025 19:43
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting Review in FilOz Dec 1, 2025
Gemini Agent and others added 6 commits December 5, 2025 12:28
Refactor FVM's reservation telemetry to be per-executor rather than a global singleton.

This resolves a potential issue where concurrent reservation sessions (e.g., in multi-threaded environments or parallel block validation) could overwrite telemetry data, leading to incorrect metrics.

The global  and  were removed from  and the telemetry functions were converted into methods of the  struct.

The  struct is now embedded within the  in , ensuring each executor's session maintains its own isolated telemetry. All call sites were updated to use this per-session instance, acquiring the  lock where necessary.
The reservation session mutex in the FVM executor's  method was previously held during I/O-intensive state tree lookups and actor state loads.

This could lead to increased contention and block other threads in multi-threaded environments or when dealing with slow blockstores.

This commit refactors the  method to:

1. Perform all state tree lookups, address resolution, and affordability checks *before* acquiring the  mutex.

2. Acquire the mutex only when it's necessary to update the  state and its associated telemetry.

3. Introduce a  helper (using a  clone) to enable telemetry updates in error paths without holding the main session lock, ensuring failures are still logged appropriately.

4. Re-check  after acquiring the lock to handle potential race conditions where another thread might have opened a session concurrently.

This significantly reduces the critical section of the code, improving concurrency and performance.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Also fix a build error in  where the  module was being accessed directly instead of using the  closure.
This commit adds two new test cases to :

1. : Verifies that providing a negative reservation amount returns a  error and correctly increments the failure telemetry counter.

2. : Comprehensively tests the lifecycle of the telemetry state, ensuring success/failure counters and open session gauges are updated correctly during session begin and end.

These tests address missing patch coverage reported by Codecov.
@snissn
Copy link
Contributor Author

snissn commented Dec 5, 2025

@copilot can you run a new review?

Copy link
Contributor

Copilot AI commented Dec 5, 2025

@snissn I've opened a new pull request, #2242, to work on those changes. Once the pull request is ready, I'll request review from you.

@snissn
Copy link
Contributor Author

snissn commented Dec 5, 2025

( ok review requests from co_pilot can be initiated by clicking an icon next to their name in the reviewers box in the top right corner)

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

Labels

None yet

Projects

Status: 🔎 Awaiting Review

Development

Successfully merging this pull request may close these issues.

3 participants