diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52903088..170f733c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,6 +100,14 @@ jobs: with: submodules: recursive ref: ${{ github.event.inputs.ref }} + - if: runner.os == 'Linux' + name: Install GCC 12 and set environment + run: | + sudo apt-get update + sudo apt-get install -y gcc-12 g++-12 + echo "CC=gcc-12" >> $GITHUB_ENV + echo "CXX=g++-12" >> $GITHUB_ENV + echo "NVCC_PREPEND_FLAGS=-allow-unsupported-compiler" >> $GITHUB_ENV - if: runner.os == 'macOS' run: cd rust && cargo fetch - name: Build project @@ -142,7 +150,7 @@ jobs: env: CC: gcc-12 CXX: g++-12 - NVCC_PREPEND_FLAGS: "-ccbin /usr/bin/g++-12" + NVCC_PREPEND_FLAGS: "-allow-unsupported-compiler" steps: - uses: actions/checkout@v4 with: @@ -153,5 +161,9 @@ jobs: with: submodules: recursive ref: ${{ github.event.inputs.ref }} + - name: Install GCC 12 + run: | + sudo apt-get update + sudo apt-get install -y gcc-12 g++-12 - name: Build project with `FFI_USE_CUDA_SUPRASEAL=1` run: FFI_BUILD_FROM_SOURCE=1 FFI_USE_CUDA_SUPRASEAL=1 make diff --git a/cgo/errors.go b/cgo/errors.go index d7e796c8..061930a7 100644 --- a/cgo/errors.go +++ b/cgo/errors.go @@ -4,6 +4,22 @@ package cgo // #cgo darwin LDFLAGS: ${SRCDIR}/../libfilcrypto.a -Wl,-undefined,dynamic_lookup // #cgo pkg-config: ${SRCDIR}/../filcrypto.pc // #include "../filcrypto.h" +// // Provide fallbacks when FVM is not compiled into filcrypto +// #ifndef FVM_ERROR_INVALID_HANDLE +// #define FVM_ERROR_INVALID_HANDLE -1 +// #endif +// #ifndef FVM_ERROR_NOT_FOUND +// #define FVM_ERROR_NOT_FOUND -2 +// #endif +// #ifndef FVM_ERROR_IO +// #define FVM_ERROR_IO -3 +// #endif +// #ifndef FVM_ERROR_INVALID_ARGUMENT +// #define FVM_ERROR_INVALID_ARGUMENT -4 +// #endif +// #ifndef FVM_ERROR_PANIC +// #define FVM_ERROR_PANIC -5 +// #endif import "C" import ( "fmt" diff --git a/cgo/fvm.go b/cgo/fvm.go index c4f2b9af..38affcf6 100644 --- a/cgo/fvm.go +++ b/cgo/fvm.go @@ -1,3 +1,5 @@ +//go:build fvm + package cgo /* diff --git a/cgo/types.go b/cgo/types.go index 46217dfb..a6da696e 100644 --- a/cgo/types.go +++ b/cgo/types.go @@ -18,7 +18,7 @@ type RegisteredAggregationProof C.RegisteredAggregationProof_t type RegisteredPoStProof C.RegisteredPoStProof_t type RegisteredUpdateProof C.RegisteredUpdateProof_t -type FvmRegisteredVersion C.FvmRegisteredVersion_t +// FVM types moved to types_fvm.go behind build tag type AggregationInputs C.AggregationInputs_t @@ -49,8 +49,7 @@ type ByteArray32 C.uint8_32_array_t type ByteArray48 C.uint8_48_array_t type ByteArray96 C.uint8_96_array_t -type FvmMachine C.InnerFvmMachine_t -type FvmMachineExecuteResponse C.FvmMachineExecuteResponse_t +// FVM types moved to types_fvm.go behind build tag type resultBool C.Result_bool_t type resultGeneratePieceCommitment C.Result_GeneratePieceCommitment_t @@ -70,8 +69,7 @@ type resultGenerateFallbackSectorChallenges C.Result_GenerateFallbackSectorChall type resultGenerateSingleWindowPoStWithVanilla C.Result_GenerateSingleWindowPoStWithVanilla_t type resultPoStProof C.Result_PoStProof_t -type resultFvmMachine C.Result_InnerFvmMachine_ptr_t -type resultFvmMachineExecuteResponse C.Result_FvmMachineExecuteResponse_t +// FVM types moved to types_fvm.go behind build tag type result interface { statusCode() FCPResponseStatus @@ -606,63 +604,10 @@ func (ptr *PoStProof) Destroy() { } } -func (ptr *resultFvmMachineExecuteResponse) statusCode() FCPResponseStatus { - return FCPResponseStatus(ptr.status_code) -} - -func (ptr *resultFvmMachineExecuteResponse) errorMsg() *SliceBoxedUint8 { - return (*SliceBoxedUint8)(&ptr.error_msg) -} - -func (ptr *resultFvmMachineExecuteResponse) destroy() { - if ptr != nil { - C.destroy_fvm_machine_execute_response((*C.Result_FvmMachineExecuteResponse_t)(ptr)) - ptr = nil - } -} - -func (ptr *resultFvmMachine) statusCode() FCPResponseStatus { - return FCPResponseStatus(ptr.status_code) -} +// FVM helpers moved to types_fvm.go -func (ptr *resultFvmMachine) errorMsg() *SliceBoxedUint8 { - return (*SliceBoxedUint8)(&ptr.error_msg) -} +// FVM helpers moved to types_fvm.go -func (ptr *resultFvmMachine) destroy() { - if ptr != nil { - C.destroy_create_fvm_machine_response((*C.Result_InnerFvmMachine_ptr_t)(ptr)) - ptr = nil - } -} +// FVM helpers moved to types_fvm.go -func (ptr *FvmMachine) Destroy() { - if ptr != nil { - C.drop_fvm_machine((*C.InnerFvmMachine_t)(ptr)) - ptr = nil - } -} - -func (r FvmMachineExecuteResponse) copy() FvmMachineExecuteResponseGo { - return FvmMachineExecuteResponseGo{ - ExitCode: uint64(r.exit_code), - ReturnVal: (*SliceBoxedUint8)(&r.return_val).copy(), - GasUsed: uint64(r.gas_used), - PenaltyHi: uint64(r.penalty_hi), - PenaltyLo: uint64(r.penalty_lo), - MinerTipHi: uint64(r.miner_tip_hi), - MinerTipLo: uint64(r.miner_tip_lo), - BaseFeeBurnHi: uint64(r.base_fee_burn_hi), - BaseFeeBurnLo: uint64(r.base_fee_burn_lo), - OverEstimationBurnHi: uint64(r.over_estimation_burn_hi), - OverEstimationBurnLo: uint64(r.over_estimation_burn_lo), - RefundHi: uint64(r.refund_hi), - RefundLo: uint64(r.refund_lo), - GasRefund: int64(r.gas_refund), - GasBurned: int64(r.gas_burned), - ExecTrace: (*SliceBoxedUint8)(&r.exec_trace).copy(), - FailureInfo: string((*SliceBoxedUint8)(&r.failure_info).slice()), - Events: (*SliceBoxedUint8)(&r.events).copy(), - EventsRoot: (*SliceBoxedUint8)(&r.events_root).copy(), - } -} +// FVM helpers moved to types_fvm.go diff --git a/cgo/types_fvm.go b/cgo/types_fvm.go new file mode 100644 index 00000000..ea27e684 --- /dev/null +++ b/cgo/types_fvm.go @@ -0,0 +1,80 @@ +//go:build fvm + +package cgo + +/* +#cgo LDFLAGS: -L${SRCDIR}/.. +#cgo pkg-config: ${SRCDIR}/../filcrypto.pc +#include "../filcrypto.h" +#include +*/ +import "C" + +type FvmRegisteredVersion C.FvmRegisteredVersion_t + +type FvmMachine C.InnerFvmMachine_t +type FvmMachineExecuteResponse C.FvmMachineExecuteResponse_t + +type resultFvmMachine C.Result_InnerFvmMachine_ptr_t +type resultFvmMachineExecuteResponse C.Result_FvmMachineExecuteResponse_t + +func (ptr *resultFvmMachineExecuteResponse) statusCode() FCPResponseStatus { + return FCPResponseStatus(ptr.status_code) +} + +func (ptr *resultFvmMachineExecuteResponse) errorMsg() *SliceBoxedUint8 { + return (*SliceBoxedUint8)(&ptr.error_msg) +} + +func (ptr *resultFvmMachineExecuteResponse) destroy() { + if ptr != nil { + C.destroy_fvm_machine_execute_response((*C.Result_FvmMachineExecuteResponse_t)(ptr)) + ptr = nil + } +} + +func (ptr *resultFvmMachine) statusCode() FCPResponseStatus { + return FCPResponseStatus(ptr.status_code) +} + +func (ptr *resultFvmMachine) errorMsg() *SliceBoxedUint8 { + return (*SliceBoxedUint8)(&ptr.error_msg) +} + +func (ptr *resultFvmMachine) destroy() { + if ptr != nil { + C.destroy_create_fvm_machine_response((*C.Result_InnerFvmMachine_ptr_t)(ptr)) + ptr = nil + } +} + +func (ptr *FvmMachine) Destroy() { + if ptr != nil { + C.drop_fvm_machine((*C.InnerFvmMachine_t)(ptr)) + ptr = nil + } +} + +func (r FvmMachineExecuteResponse) copy() FvmMachineExecuteResponseGo { + return FvmMachineExecuteResponseGo{ + ExitCode: uint64(r.exit_code), + ReturnVal: (*SliceBoxedUint8)(&r.return_val).copy(), + GasUsed: uint64(r.gas_used), + PenaltyHi: uint64(r.penalty_hi), + PenaltyLo: uint64(r.penalty_lo), + MinerTipHi: uint64(r.miner_tip_hi), + MinerTipLo: uint64(r.miner_tip_lo), + BaseFeeBurnHi: uint64(r.base_fee_burn_hi), + BaseFeeBurnLo: uint64(r.base_fee_burn_lo), + OverEstimationBurnHi: uint64(r.over_estimation_burn_hi), + OverEstimationBurnLo: uint64(r.over_estimation_burn_lo), + RefundHi: uint64(r.refund_hi), + RefundLo: uint64(r.refund_lo), + GasRefund: int64(r.gas_refund), + GasBurned: int64(r.gas_burned), + ExecTrace: (*SliceBoxedUint8)(&r.exec_trace).copy(), + FailureInfo: string((*SliceBoxedUint8)(&r.failure_info).slice()), + Events: (*SliceBoxedUint8)(&r.events).copy(), + EventsRoot: (*SliceBoxedUint8)(&r.events_root).copy(), + } +} diff --git a/fvm.go b/fvm.go index e73a6647..81cf2b6c 100644 --- a/fvm.go +++ b/fvm.go @@ -1,6 +1,7 @@ -//go:build cgo && (amd64 || arm64 || riscv64) +//go:build cgo && (amd64 || arm64 || riscv64) && fvm // +build cgo // +build amd64 arm64 riscv64 +// +build fvm package ffi diff --git a/fvm_stub.go b/fvm_stub.go new file mode 100644 index 00000000..302a3d90 --- /dev/null +++ b/fvm_stub.go @@ -0,0 +1,92 @@ +//go:build !fvm + +package ffi + +import ( + "context" + "errors" + + "github.com/filecoin-project/filecoin-ffi/cgo" + "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/go-state-types/big" + "github.com/filecoin-project/go-state-types/network" + "github.com/ipfs/go-cid" + "golang.org/x/xerrors" +) + +type FVM struct{} + +type FVMOpts struct { + FVMVersion uint64 + Externs cgo.Externs + + Epoch abi.ChainEpoch + Timestamp uint64 + ChainID uint64 + BaseFee abi.TokenAmount + BaseCircSupply abi.TokenAmount + NetworkVersion network.Version + StateBase cid.Cid + Tracing bool + FlushAllBlocks bool + + Debug bool + ActorRedirect cid.Cid +} + +func CreateFVM(opts *FVMOpts) (*FVM, error) { + return nil, errors.New("FVM support not built in this binary") +} + +func (f *FVM) ApplyMessage(_ []byte, _ uint) (*ApplyRet, error) { + return nil, errors.New("FVM support not built in this binary") +} + +func (f *FVM) ApplyImplicitMessage(_ []byte) (*ApplyRet, error) { + return nil, errors.New("FVM support not built in this binary") +} + +func (f *FVM) Flush() (cid.Cid, error) { + return cid.Undef, errors.New("FVM support not built in this binary") +} + +// Minimal stubs to satisfy references +type ApplyRet struct { + Return []byte + ExitCode uint64 + GasUsed int64 + MinerPenalty abi.TokenAmount + MinerTip abi.TokenAmount + BaseFeeBurn abi.TokenAmount + OverEstimationBurn abi.TokenAmount + Refund abi.TokenAmount + GasRefund int64 + GasBurned int64 + ExecTraceBytes []byte + FailureInfo string + EventsRoot *cid.Cid + EventsBytes []byte +} + +// Ensure cgo.Externs referenced to avoid unused import when stubbed +var _ = func() any { return context.TODO() } + +// splitBigInt splits a big.Int into high and low uint64 values. +// This is used by tests and needs to be available even when FVM is not built. +func splitBigInt(i big.Int) (hi uint64, lo uint64, err error) { + if i.Sign() < 0 { + return 0, 0, xerrors.Errorf("negative number: %s", i) + } + words := i.Bits() + switch len(words) { + case 2: + hi = uint64(words[1]) + fallthrough + case 1: + lo = uint64(words[0]) + case 0: + default: + return 0, 0, xerrors.Errorf("exceeds max bigint size: %s", i) + } + return hi, lo, nil +} diff --git a/install-filcrypto b/install-filcrypto index 6c585f55..f6b26533 100755 --- a/install-filcrypto +++ b/install-filcrypto @@ -232,12 +232,24 @@ build_from_source() { use_fixed_rows_to_discard=",fixed-rows-to-discard" fi - additional_flags="" - # Add feature specific rust flags as needed here. + # Collect features into an array, stripping leading commas as we go + features=() + [ -n "${use_multicore_sdr}" ] && features+=("${use_multicore_sdr}") + + [ -n "${gpu_flags}" ] && features+=("${gpu_flags#,}") + [ "${FFI_DISABLE_FVM}" != "1" ] && features+=("fvm") + [ -n "${use_fixed_rows_to_discard}" ] && features+=("${use_fixed_rows_to_discard#,}") if [ "${FFI_USE_BLST_PORTABLE}" == "1" ] || [ "${FFI_PORTABLE}" == "1" ]; then - additional_flags="${additional_flags} --no-default-features --features ${use_multicore_sdr},blst-portable${gpu_flags}${use_fixed_rows_to_discard}" + features+=("blst-portable") + fi + + # Join features with commas + feature_list=$(IFS=','; printf '%s' "${features[*]}") + + if [ -n "${feature_list}" ]; then + additional_flags="--no-default-features --features ${feature_list}" else - additional_flags="${additional_flags} --no-default-features --features ${use_multicore_sdr}${gpu_flags}${use_fixed_rows_to_discard}" + additional_flags="--no-default-features" fi echo "Using additional build flags: ${additional_flags}" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 421fd9b4..ddc05dec 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -33,14 +33,14 @@ rayon = "1.10.0" anyhow = "1.0.97" serde_json = "1.0.140" rust-gpu-tools = { version = "0.7", optional = true, default-features = false } -fvm4 = { package = "fvm", version = "~4.7.4", default-features = false, features = ["verify-signature", "nv28-dev"] } -fvm4_shared = { package = "fvm_shared", version = "~4.7.4" } -fvm3 = { package = "fvm", version = "~3.13.0", default-features = false } -fvm3_shared = { package = "fvm_shared", version = "~3.13.0" } -fvm2 = { package = "fvm", version = "~2.11.0", default-features = false } -fvm2_shared = { package = "fvm_shared", version = "~2.11.0" } -fvm_ipld_encoding = "0.5.3" -fvm_ipld_blockstore = "0.3.1" +fvm4 = { package = "fvm", version = "~4.7.4", default-features = false, features = ["verify-signature", "nv28-dev"], optional = true } +fvm4_shared = { package = "fvm_shared", version = "~4.7.4", optional = true } +fvm3 = { package = "fvm", version = "~3.13.0", default-features = false, optional = true } +fvm3_shared = { package = "fvm_shared", version = "~3.13.0", optional = true } +fvm2 = { package = "fvm", version = "~2.11.0", default-features = false, optional = true } +fvm2_shared = { package = "fvm_shared", version = "~2.11.0", optional = true } +fvm_ipld_encoding = { version = "0.5.3", optional = true } +fvm_ipld_blockstore = { version = "0.3.1", optional = true } num-traits = "0.2.19" cid = { version = "0.11.1", features = ["serde"], default-features = false } lazy_static = "1.5.0" @@ -54,7 +54,18 @@ memmap2 = "0.9" tempfile = "3.19.1" [features] -default = ["cuda", "multicore-sdr"] +default = ["cuda", "multicore-sdr", "fvm"] +fvm = [ + "fvm2", + "fvm3", + "fvm4", + "fvm2_shared", + "fvm3_shared", + "fvm4_shared", + "fvm_ipld_encoding", + "fvm_ipld_blockstore", +] +curio = [] blst-portable = ["bls-signatures/blst-portable", "blstrs/portable"] cuda = [ "filecoin-proofs-api/cuda", diff --git a/rust/scripts/build-release.sh b/rust/scripts/build-release.sh index b93c2876..0ed6fe8b 100755 --- a/rust/scripts/build-release.sh +++ b/rust/scripts/build-release.sh @@ -73,10 +73,13 @@ main() { fi # generate filcrypto.h - # The header files are the same even without having any features enables, - # this reduces the compile time and makes it work on more platforms. + # Check if FVM is in the build features - if so, include it in header generation + local __header_features="c-headers" + if echo "${@:2}" | grep -q "fvm"; then + __header_features="c-headers,fvm" + fi RUSTFLAGS="${__rust_flags}" HEADER_DIR="." \ - cargo test --no-default-features --locked build_headers --features c-headers + cargo test --no-default-features --locked build_headers --features ${__header_features} # generate pkg-config # diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 8fd99b13..81e7e681 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -3,10 +3,12 @@ #![allow(clippy::upper_case_acronyms)] pub mod bls; -pub mod fvm; pub mod proofs; pub mod util; +#[cfg(feature = "fvm")] +pub mod fvm; + // Generates the headers. // Run `HEADER_DIR= cargo test --locked build_headers --features c-headers` to build #[safer_ffi::cfg_headers]