-
Notifications
You must be signed in to change notification settings - Fork 152
feat: add engine‑managed tipset gas reservations to ref‑fvm #2236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
770523f to
56c2695
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ 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
🚀 New features to boost your workflow:
|
There was a problem hiding this 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
ReservationSessionledger 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.
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.
|
@copilot can you run a new review? |
|
( 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) |
There was a problem hiding this 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.
There was a problem hiding this 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.
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
ActorID.begin_reservation_session/end_reservation_sessionwith affordability checks and invariants.balance − reserved_remaining.Changes
Executor: session lifecycle and preflight
fvm/src/executor/mod.rsReservationSessionstruct (re‑exported fromdefault.rs) andReservationErrorenum:NotImplementedInsufficientFundsAtBegin { sender }SessionOpenSessionClosedNonZeroRemainderPlanTooLargeOverflowReservationInvariant(String)fvm/src/executor/default.rsReservationSession { reservations: HashMap<ActorID, TokenAmount>, open: bool }and anArc<Mutex<_>>onDefaultExecutor.begin_reservation_session(&mut self, plan: &[(Address, TokenAmount)]) -> Result<(), ReservationError>:MAX_SENDERS(65,536) and track plan failures via telemetry.ActorID).reserved_total <= balanceper sender.end_reservation_session(&mut self) -> Result<(), ReservationError>:open == trueand all reservation entries to be zero.gas_cost = gas_fee_cap * gas_limitusing big‑int; treat negative results asReservationError::Overflow.reservation_assert_coverage(sender, &gas_cost); do not pre‑deduct funds.reservation_prevalidation_decrementso the ledger can end at zero.Transfer enforcement and settlement
fvm/src/call_manager/default.rs&fvm/src/call_manager/mod.rsArc<Mutex<ReservationSession>>into the default call manager.transfer(from, to, value):reserved_remaining = reservations.get(from).unwrap_or(0).value + reserved_remaining <= from.balance; otherwise returnInsufficientFunds.value <= balancesemantics.fvm/src/executor/default.rsfinish_message) in reservation mode:GasOutputsas today.consumption = base_fee_burn + over_estimation_burn + miner_tip.consumptionfrom the sender’s actor balance.refundto the sender; the “refund effect” is realized by releasing the reservation ledger.reservations[sender]bygas_costusingreservation_prevalidation_decrement, update telemetry, and remove entries at zero.base_fee_burn + over_estimation_burn + refund + miner_tip == gas_cost.Telemetry
fvm/src/executor/telemetry.rsReservationTelemetryand helpers:reservations_openreservation_begin_failedsettle_basefee_burnsettle_tip_creditsettle_overburnsettle_refund_virtualsnapshot()(for potential host export) andreset()under#[cfg(test)].Kernel and test harness adjustments
fvm/src/kernel/default.rsCallManagertype where necessary so that all value‑moving operations (SendOps, SELFDESTRUCT, etc.) route through the reservation‑awaretransfer.fvm/tests/dummy.rsCallManagerimpl to accept the newReservationSessionargument inCallManager::new, keeping tests compiling against the updated trait.Tests
Unit tests in
fvm/src/executor/default.rs:ReservationError::Overflow.transfer, send to existing actors, SELFDESTRUCT, and implicit sends must respect free balance.consumption.end_reservation_sessionsucceeds.--features arb) continues to assert:base_fee_burn + over_estimation_burn + refund + miner_tip == gas_cost.Integration tests:
testing/integration/tests/reservation_transfer_enforcement.rs:value > free = balance − reserved_remaining.Activation and host behaviour
begin_reservation_session/end_reservation_session.ReservationErrorvariants (legacy fallback, tipset invalid, node error) based on network version and feature flags.Notes
ExitCode,GasUsed, events) andGasOutputsrelative to pre‑reservation behaviour, while removing miner exposure to intra‑tipset underfunded messages when hosts enable reservations.