Skip to content

Conversation

@snissn
Copy link

@snissn snissn commented Nov 18, 2025

Summary

This PR adds FFI bindings for the new tipset reservation session API required by the Multi‑Stage Tipset Gas Reservations work.

Specifically, it:

  • Extends the C FFI with Begin/End reservation session entrypoints and associated status codes.
  • Wires new Go wrappers in cgo/fvm.go to call the reservation API and surface structured errors to Lotus.
  • Introduces a new Rust reservations module in rust/src/fvm and hooks it into mod.rs.

These bindings are used by Lotus to start and end a reservation session around tipset execution while keeping the reservation implementation inside ref‑fvm.

Motivation

Lotus and ref‑fvm are adding tipset‑scope gas reservations to eliminate miner‑penalty exposure from intra‑tipset self‑drain scenarios, as described in the draft FIP
“Multi‑Stage Tipset Gas Reservations”.

filecoin‑ffi needs to expose the engine’s reservation session API (Begin/End and error reporting) to Go so that Lotus can orchestrate reservations at the tipset boundary
without introducing new on‑chain actors or migrations.

Changes

  • cgo/fvm.go:
    • Adds FFI wrappers that call the engine’s reservation Begin/End API.
    • Propagates reservation error codes and messages into Go.
  • cgo/fvm_reservations.go:
    • New Go helpers for reservation management, used by Lotus’ FVM VM wrapper.
  • rust/src/fvm/mod.rs:
    • Registers the new reservations submodule.
  • rust/src/fvm/reservations.rs:
    • Defines the Rust side of the reservation FFI surface.

Testing

  • go test ./... in this repo.
  • Rebuilt Lotus with this branch as the extern/filecoin-ffi submodule and ran the existing FVM/consensus test suites that exercise FFI calls.

@snissn
Copy link
Author

snissn commented Nov 18, 2025

@snissn snissn marked this pull request as ready for review November 21, 2025 00:47
Copilot AI review requested due to automatic review settings November 21, 2025 00:47
Copy link

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 adds FFI bindings for FVM reservation session management, enabling Lotus to orchestrate gas reservations at tipset boundaries. The implementation spans Rust FFI exports, CGO wrappers, and Go public APIs.

Key Changes:

  • Adds FVM_BeginReservations and FVM_EndReservations FFI exports with status codes and error messages
  • Introduces reservation error types and status-to-error mapping in both Rust and Go
  • Implements error message allocation/deallocation across the FFI boundary

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
rust/src/fvm/machine.rs Implements FFI exports for Begin/End reservation sessions, error message handling, and tracks current machine in global state
rust/src/fvm/engine.rs Defines ReservationError enum and default trait methods for reservation operations
cgo/fvm.go Provides CGO wrappers that invoke C ABI and manage error message memory
fvm.go Exposes typed reservation errors and high-level BeginReservations/EndReservations methods on FVM instances
cgo/fvm_reservations_test.go Tests error message handling for invalid reservation calls

💡 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:32
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting Review in FilOz Dec 1, 2025
@snissn snissn requested a review from Copilot December 6, 2025 00:25
Copy link

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 6 out of 7 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

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 6 out of 7 changed files in this pull request and generated 5 comments.


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

Copy link

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 6 out of 7 changed files in this pull request and generated 4 comments.


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

const LOTUS_FVM_CONCURRENCY_ENV_NAME: &str = "LOTUS_FVM_CONCURRENCY";
const VALID_CONCURRENCY_RANGE: RangeInclusive<u32> = 1..=256;

#[derive_ReprC]
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The derive_ReprC attribute appears to be used here, but it's not a standard Rust derive macro. This seems to be from the safer_ffi crate or similar. Please verify that this crate is properly included in dependencies and that this is the intended FFI representation mechanism.

Copilot uses AI. Check for mistakes.
Comment on lines +617 to +619
// Enforce a maximum encoded plan size (256 KiB).
// This is based on a maximum of 4096 entries at 64 bytes per entry.
const MAX_PLAN_BYTES: usize = 256 * 1024;
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The MAX_PLAN_BYTES constant of 256 KiB (based on 4096 entries × 64 bytes) should be validated against the actual CBOR encoding size of a Vec<(Address, TokenAmount)>. The comment suggests 64 bytes per entry, but a CBOR-encoded Address (41+ bytes) plus TokenAmount (variable) plus CBOR overhead may exceed this estimate, especially for addresses with longer protocols or large token amounts. Consider adding a test that verifies a plan with 4096 entries actually fits within this limit.

Copilot uses AI. Check for mistakes.
Comment on lines +641 to +650
let plan: Vec<(Address, TokenAmount)> = match fvm_ipld_encoding::from_slice(bytes) {
Ok(p) => p,
Err(_) => {
set_reservation_error_message_out(
error_msg_ptr_out,
error_msg_len_out,
"reservation invariant violated: invalid plan CBOR encoding",
);
return FvmReservationStatus::ErrReservationInvariant;
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

The CBOR decoding error at line 643 is classified as ErrReservationInvariant with message "invalid plan CBOR encoding". However, this is not an invariant violation—it's invalid input from the caller. Consider either: (1) Adding a new error variant like InvalidPlanEncoding to distinguish client errors from internal invariant violations, or (2) Accepting any decoding error as OK with an empty-plan semantics if the intent is to be lenient. The current classification may make debugging harder by conflating different error categories.

Copilot uses AI. Check for mistakes.
Comment on lines +968 to +992
fn reservation_error_mapping_sets_message_for_insufficient_funds() {
let mut msg_ptr: *const u8 = std::ptr::null();
let mut msg_len: usize = 0;

let status = map_reservation_error_to_status(
ReservationError::InsufficientFundsAtBegin { sender: 42 },
&mut msg_ptr,
&mut msg_len,
);

assert_eq!(status, FvmReservationStatus::ErrInsufficientFundsAtBegin);
assert!(!msg_ptr.is_null());
assert!(msg_len > 0);

let msg = unsafe {
let slice = std::slice::from_raw_parts(msg_ptr, msg_len);
std::str::from_utf8(slice).expect("reservation error message is valid UTF-8")
};
assert!(
msg.contains("sender 42"),
"expected message to contain sender id, got {msg}"
);

FVM_DestroyReservationErrorMessage(msg_ptr as *mut u8, msg_len);
}
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

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

[nitpick] The map_reservation_error_to_status function at line 972-976 tests InsufficientFundsAtBegin with a hardcoded sender ID of 42, but the test doesn't verify that this sender ID actually appears in the returned error message. The assertion at line 987 uses contains("sender 42") which could pass even if the formatting is incorrect. Consider adding an assertion that checks for the exact expected format or at minimum verifies the sender ID is present as a number.

Copilot uses AI. Check for mistakes.
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.

1 participant