From 7b4642bb39e2902a1b3322eec226667788ac61dc Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 4 Sep 2024 14:16:24 +0800 Subject: [PATCH 1/8] feat: build and run F3 sidecar in Forest process via FFI --- .github/workflows/forest.yml | 8 ++ Cargo.lock | 1 + Cargo.toml | 4 + Makefile | 2 + build.rs | 35 ++++++ f3-sidecar/README.md | 11 ++ f3-sidecar/ffi_gen.go | 210 +++++++++++++++++++++++++++++++++++ f3-sidecar/ffi_impl.go | 39 +++++++ src/daemon/mod.rs | 14 +++ src/f3/go_ffi.rs | 21 ++++ src/f3/mod.rs | 50 +++++++++ src/lib.rs | 1 + src/rpc/methods/f3.rs | 2 +- 13 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 build.rs create mode 100644 f3-sidecar/ffi_gen.go create mode 100644 f3-sidecar/ffi_impl.go create mode 100644 src/f3/go_ffi.rs create mode 100644 src/f3/mod.rs diff --git a/.github/workflows/forest.yml b/.github/workflows/forest.yml index b1f65dc91409..2aa632296aed 100644 --- a/.github/workflows/forest.yml +++ b/.github/workflows/forest.yml @@ -47,6 +47,9 @@ jobs: uses: mozilla-actions/sccache-action@v0.0.5 timeout-minutes: '${{ fromJSON(env.CACHE_TIMEOUT_MINUTES) }}' continue-on-error: true + - uses: actions/setup-go@v5 + with: + go-version-file: "go.work" - name: Cargo Check run: cargo check build-ubuntu: @@ -71,6 +74,9 @@ jobs: uses: mozilla-actions/sccache-action@v0.0.5 timeout-minutes: '${{ fromJSON(env.CACHE_TIMEOUT_MINUTES) }}' continue-on-error: true + - uses: actions/setup-go@v5 + with: + go-version-file: "go.work" - name: Cargo Install env: # To minimize compile times: https://nnethercote.github.io/perf-book/build-configuration.html#minimizing-compile-times @@ -95,6 +101,8 @@ jobs: run: | sudo make install-deps - run: cargo publish --dry-run + env: + FOREST_F3_SIDECAR_FFI_BUILD_OPT_OUT: 1 forest-cli-check: needs: - build-ubuntu diff --git a/Cargo.lock b/Cargo.lock index 09b7a9b24011..2d70b425da4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3275,6 +3275,7 @@ dependencies = [ "rlimit", "rlp", "rs-car-ipfs", + "rust2go", "schemars", "scopeguard", "semver", diff --git a/Cargo.toml b/Cargo.toml index 1cdec90644c3..59c66465cfdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -153,6 +153,7 @@ reqwest = { version = "0.12", default-features = false, features = [ rlimit = "0.10" rlp = "0.5" rs-car-ipfs = "0.3" +rust2go = { version = "0.3" } schemars = { version = "0.8", features = ["chrono", "uuid1"] } scopeguard = "1" semver = "1" @@ -228,6 +229,9 @@ regex-automata = "0.4" syn = { version = "2", default-features = false, features = ["full", "parsing", "visit", "printing", "extra-traits"] } tokio-test = "0.4" +[build-dependencies] +rust2go = { version = "0.3", features = ["build"] } + # This needs to be set as default. Otherwise, a regular build or test will produce # gargantuan artifacts (around 70G for all tests). For a debugging session, you can # temporarily comment it out. diff --git a/Makefile b/Makefile index a7d72e78fa77..49dc0b1ba5b6 100644 --- a/Makefile +++ b/Makefile @@ -82,6 +82,8 @@ lint-clippy: cargo clippy --all-targets --no-default-features --features slim --quiet --no-deps -- --deny=warnings cargo clippy --all-targets --no-default-features --quiet --no-deps -- --deny=warnings cargo clippy --benches --features benchmark-private --quiet --no-deps -- --deny=warnings + # check docs.rs build + DOCS_RS=1 cargo clippy --all-targets --quiet --no-deps -- --deny=warnings DOCKERFILES=$(wildcard Dockerfile*) lint-docker: $(DOCKERFILES) diff --git a/build.rs b/build.rs new file mode 100644 index 000000000000..5b494375f858 --- /dev/null +++ b/build.rs @@ -0,0 +1,35 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +fn main() { + // whitelist the cfg for cargo clippy + println!("cargo::rustc-check-cfg=cfg(f3sidecar)"); + + // Do not build f3-sidecar on docs.rs publishing + // No proper version of Go compiler is available. + if !is_docs_rs() && is_sidecar_ffi_enabled() { + println!("cargo:rustc-cfg=f3sidecar"); + rust2go::Builder::default() + .with_go_src("./f3-sidecar") + .with_regen_arg(rust2go::RegenArgs { + src: "./src/f3/go_ffi.rs".into(), + dst: "./f3-sidecar/ffi_gen.go".into(), + without_main: true, + ..Default::default() + }) + .build(); + } +} + +// See +fn is_docs_rs() -> bool { + std::env::var("DOCS_RS").is_ok() +} + +fn is_sidecar_ffi_enabled() -> bool { + // Opt-out building the F3 sidecar staticlib + match std::env::var("FOREST_F3_SIDECAR_FFI_BUILD_OPT_OUT") { + Ok(value) => !matches!(value.to_lowercase().as_str(), "1" | "true"), + _ => true, + } +} diff --git a/f3-sidecar/README.md b/f3-sidecar/README.md index 02e11e5c5ef8..0be6231797bd 100644 --- a/f3-sidecar/README.md +++ b/f3-sidecar/README.md @@ -47,3 +47,14 @@ flowchart TD A --> |storage backend| C[level db] A --> |dynamic manifest backend| D[manifest p2p server] ``` + +### To build and run F3 sidecar within Forest via FFI + +By default, the Go F3-sidecar is built and linked into Forest binary unless +environment variable `FOREST_F3_SIDECAR_FFI_BUILD_OPT_OUT=1` is set. + +F3 sidecar is not started by default, set `FOREST_F3_SIDECAR_FFI_ENABLED=1` to +opt in. + +Set dynamic manifest server via `FOREST_F3_MANIFEST_SERVER`, e.g. +`FOREST_F3_MANIFEST_SERVER=12D3KooWENMwUF9YxvQxar7uBWJtZkA6amvK4xWmKXfSiHUo2Qq7` diff --git a/f3-sidecar/ffi_gen.go b/f3-sidecar/ffi_gen.go new file mode 100644 index 000000000000..4e8863827a0a --- /dev/null +++ b/f3-sidecar/ffi_gen.go @@ -0,0 +1,210 @@ +package main + +/* +// Generated by rust2go. Please DO NOT edit this C part manually. + +#include +#include +#include +#include + +typedef struct EmptyReqRef { + +} EmptyReqRef; + +typedef struct ListRef { + const void *ptr; + uintptr_t len; +} ListRef; + +typedef struct StringRef { + const uint8_t *ptr; + uintptr_t len; +} StringRef; + +// hack from: https://stackoverflow.com/a/69904977 +__attribute__((weak)) +inline void GoF3Node_run_cb(const void *f_ptr, bool resp, const void *slot) { +((void (*)(bool, const void*))f_ptr)(resp, slot); +} +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +var GoF3NodeImpl GoF3Node + +type GoF3Node interface { + run(rpc_endpoint string, f3_rpc_endpoint string, finality int64, db string, manifest_server string) bool +} + +//export CGoF3Node_run +func CGoF3Node_run(rpc_endpoint C.StringRef, f3_rpc_endpoint C.StringRef, finality C.int64_t, db C.StringRef, manifest_server C.StringRef, slot *C.void, cb *C.void) { + resp := GoF3NodeImpl.run(newString(rpc_endpoint), newString(f3_rpc_endpoint), newC_int64_t(finality), newString(db), newString(manifest_server)) + resp_ref, buffer := cvt_ref(cntC_bool, refC_bool)(&resp) + C.GoF3Node_run_cb(unsafe.Pointer(cb), resp_ref, unsafe.Pointer(slot)) + runtime.KeepAlive(resp) + runtime.KeepAlive(buffer) +} + +func newString(s_ref C.StringRef) string { + return unsafe.String((*byte)(unsafe.Pointer(s_ref.ptr)), s_ref.len) +} +func refString(s *string, _ *[]byte) C.StringRef { + return C.StringRef{ + ptr: (*C.uint8_t)(unsafe.StringData(*s)), + len: C.uintptr_t(len(*s)), + } +} + +func cntString(_ *string, _ *uint) [0]C.StringRef { return [0]C.StringRef{} } +func new_list_mapper[T1, T2 any](f func(T1) T2) func(C.ListRef) []T2 { + return func(x C.ListRef) []T2 { + input := unsafe.Slice((*T1)(unsafe.Pointer(x.ptr)), x.len) + output := make([]T2, len(input)) + for i, v := range input { + output[i] = f(v) + } + return output + } +} +func new_list_mapper_primitive[T1, T2 any](_ func(T1) T2) func(C.ListRef) []T2 { + return func(x C.ListRef) []T2 { + return unsafe.Slice((*T2)(unsafe.Pointer(x.ptr)), x.len) + } +} + +// only handle non-primitive type T +func cnt_list_mapper[T, R any](f func(s *T, cnt *uint) [0]R) func(s *[]T, cnt *uint) [0]C.ListRef { + return func(s *[]T, cnt *uint) [0]C.ListRef { + for _, v := range *s { + f(&v, cnt) + } + *cnt += uint(len(*s)) * size_of[R]() + return [0]C.ListRef{} + } +} + +// only handle primitive type T +func cnt_list_mapper_primitive[T, R any](_ func(s *T, cnt *uint) [0]R) func(s *[]T, cnt *uint) [0]C.ListRef { + return func(s *[]T, cnt *uint) [0]C.ListRef { return [0]C.ListRef{} } +} + +// only handle non-primitive type T +func ref_list_mapper[T, R any](f func(s *T, buffer *[]byte) R) func(s *[]T, buffer *[]byte) C.ListRef { + return func(s *[]T, buffer *[]byte) C.ListRef { + if len(*buffer) == 0 { + return C.ListRef{ + ptr: unsafe.Pointer(nil), + len: C.uintptr_t(len(*s)), + } + } + ret := C.ListRef{ + ptr: unsafe.Pointer(&(*buffer)[0]), + len: C.uintptr_t(len(*s)), + } + children_bytes := int(size_of[R]()) * len(*s) + children := (*buffer)[:children_bytes] + *buffer = (*buffer)[children_bytes:] + for _, v := range *s { + child := f(&v, buffer) + len := unsafe.Sizeof(child) + copy(children, unsafe.Slice((*byte)(unsafe.Pointer(&child)), len)) + children = children[len:] + } + return ret + } +} + +// only handle primitive type T +func ref_list_mapper_primitive[T, R any](_ func(s *T, buffer *[]byte) R) func(s *[]T, buffer *[]byte) C.ListRef { + return func(s *[]T, buffer *[]byte) C.ListRef { + if len(*s) == 0 { + return C.ListRef{ + ptr: unsafe.Pointer(nil), + len: C.uintptr_t(0), + } + } + return C.ListRef{ + ptr: unsafe.Pointer(&(*s)[0]), + len: C.uintptr_t(len(*s)), + } + } +} +func size_of[T any]() uint { + var t T + return uint(unsafe.Sizeof(t)) +} +func cvt_ref[R, CR any](cnt_f func(s *R, cnt *uint) [0]CR, ref_f func(p *R, buffer *[]byte) CR) func(p *R) (CR, []byte) { + return func(p *R) (CR, []byte) { + var cnt uint + cnt_f(p, &cnt) + buffer := make([]byte, cnt) + return ref_f(p, &buffer), buffer + } +} +func cvt_ref_cap[R, CR any](cnt_f func(s *R, cnt *uint) [0]CR, ref_f func(p *R, buffer *[]byte) CR, add_cap uint) func(p *R) (CR, []byte) { + return func(p *R) (CR, []byte) { + var cnt uint + cnt_f(p, &cnt) + buffer := make([]byte, cnt, cnt+add_cap) + return ref_f(p, &buffer), buffer + } +} + +func newC_uint8_t(n C.uint8_t) uint8 { return uint8(n) } +func newC_uint16_t(n C.uint16_t) uint16 { return uint16(n) } +func newC_uint32_t(n C.uint32_t) uint32 { return uint32(n) } +func newC_uint64_t(n C.uint64_t) uint64 { return uint64(n) } +func newC_int8_t(n C.int8_t) int8 { return int8(n) } +func newC_int16_t(n C.int16_t) int16 { return int16(n) } +func newC_int32_t(n C.int32_t) int32 { return int32(n) } +func newC_int64_t(n C.int64_t) int64 { return int64(n) } +func newC_bool(n C.bool) bool { return bool(n) } +func newC_uintptr_t(n C.uintptr_t) uint { return uint(n) } +func newC_intptr_t(n C.intptr_t) int { return int(n) } +func newC_float(n C.float) float32 { return float32(n) } +func newC_double(n C.double) float64 { return float64(n) } + +func cntC_uint8_t(_ *uint8, _ *uint) [0]C.uint8_t { return [0]C.uint8_t{} } +func cntC_uint16_t(_ *uint16, _ *uint) [0]C.uint16_t { return [0]C.uint16_t{} } +func cntC_uint32_t(_ *uint32, _ *uint) [0]C.uint32_t { return [0]C.uint32_t{} } +func cntC_uint64_t(_ *uint64, _ *uint) [0]C.uint64_t { return [0]C.uint64_t{} } +func cntC_int8_t(_ *int8, _ *uint) [0]C.int8_t { return [0]C.int8_t{} } +func cntC_int16_t(_ *int16, _ *uint) [0]C.int16_t { return [0]C.int16_t{} } +func cntC_int32_t(_ *int32, _ *uint) [0]C.int32_t { return [0]C.int32_t{} } +func cntC_int64_t(_ *int64, _ *uint) [0]C.int64_t { return [0]C.int64_t{} } +func cntC_bool(_ *bool, _ *uint) [0]C.bool { return [0]C.bool{} } +func cntC_uintptr_t(_ *uint, _ *uint) [0]C.uintptr_t { return [0]C.uintptr_t{} } +func cntC_intptr_t(_ *int, _ *uint) [0]C.intptr_t { return [0]C.intptr_t{} } +func cntC_float(_ *float32, _ *uint) [0]C.float { return [0]C.float{} } +func cntC_double(_ *float64, _ *uint) [0]C.double { return [0]C.double{} } + +func refC_uint8_t(p *uint8, _ *[]byte) C.uint8_t { return C.uint8_t(*p) } +func refC_uint16_t(p *uint16, _ *[]byte) C.uint16_t { return C.uint16_t(*p) } +func refC_uint32_t(p *uint32, _ *[]byte) C.uint32_t { return C.uint32_t(*p) } +func refC_uint64_t(p *uint64, _ *[]byte) C.uint64_t { return C.uint64_t(*p) } +func refC_int8_t(p *int8, _ *[]byte) C.int8_t { return C.int8_t(*p) } +func refC_int16_t(p *int16, _ *[]byte) C.int16_t { return C.int16_t(*p) } +func refC_int32_t(p *int32, _ *[]byte) C.int32_t { return C.int32_t(*p) } +func refC_int64_t(p *int64, _ *[]byte) C.int64_t { return C.int64_t(*p) } +func refC_bool(p *bool, _ *[]byte) C.bool { return C.bool(*p) } +func refC_uintptr_t(p *uint, _ *[]byte) C.uintptr_t { return C.uintptr_t(*p) } +func refC_intptr_t(p *int, _ *[]byte) C.intptr_t { return C.intptr_t(*p) } +func refC_float(p *float32, _ *[]byte) C.float { return C.float(*p) } +func refC_double(p *float64, _ *[]byte) C.double { return C.double(*p) } + +type EmptyReq struct { +} + +func newEmptyReq(p C.EmptyReqRef) EmptyReq { + return EmptyReq{} +} +func cntEmptyReq(s *EmptyReq, cnt *uint) [0]C.EmptyReqRef { + return [0]C.EmptyReqRef{} +} +func refEmptyReq(p *EmptyReq, buffer *[]byte) C.EmptyReqRef { + return C.EmptyReqRef{} +} diff --git a/f3-sidecar/ffi_impl.go b/f3-sidecar/ffi_impl.go new file mode 100644 index 000000000000..6448a43fa6d9 --- /dev/null +++ b/f3-sidecar/ffi_impl.go @@ -0,0 +1,39 @@ +package main + +import ( + "context" + "os" + + logging "github.com/ipfs/go-log/v2" +) + +func init() { + setGoDebugEnv() + logging.SetAllLoggers(logging.LevelWarn) + err := logging.SetLogLevel("f3/sidecar", "info") + checkError(err) + err = logging.SetLogLevel("f3", "info") + checkError(err) + GoF3NodeImpl = &f3Impl{ctx: context.Background()} +} + +type f3Impl struct { + ctx context.Context +} + +func (f3 *f3Impl) run(rpc_endpoint string, f3_rpc_endpoint string, finality int64, db string, manifest_server string) bool { + err := run(f3.ctx, rpc_endpoint, f3_rpc_endpoint, finality, db, manifest_server) + return err == nil +} + +func checkError(err error) { + if err != nil { + panic(err) + } +} + +// To avoid potential panics +// See +func setGoDebugEnv() { + os.Setenv("GODEBUG", "invalidptr=0,cgocheck=0") +} diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs index ead0db0fdffe..aefa87096615 100644 --- a/src/daemon/mod.rs +++ b/src/daemon/mod.rs @@ -411,6 +411,20 @@ pub(super) async fn start( ) .await }); + + let finality = chain_config.policy.chain_finality; + let chain = config.chain.to_string(); + services.spawn_blocking(move || { + crate::f3::run_f3_sidecar_if_enabled( + format!("http://{rpc_address}/rpc/v1"), + crate::rpc::f3::get_f3_rpc_endpoint().to_string(), + finality, + std::env::var("FOREST_F3_DB_PATH") + .unwrap_or_else(|_| format!("/var/tmp/f3-db-{chain}")), + std::env::var("FOREST_F3_MANIFEST_SERVER").unwrap_or_default(), + ); + Ok(()) + }); } else { debug!("RPC disabled."); }; diff --git a/src/f3/go_ffi.rs b/src/f3/go_ffi.rs new file mode 100644 index 000000000000..8bbd3a9adccb --- /dev/null +++ b/src/f3/go_ffi.rs @@ -0,0 +1,21 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +pub mod binding { + #![allow(warnings)] + rust2go::r2g_include_binding!(); +} + +#[derive(rust2go::R2G, Clone, Default)] +pub struct EmptyReq {} + +#[rust2go::r2g] +pub trait GoF3Node { + fn run( + rpc_endpoint: String, + f3_rpc_endpoint: String, + finality: i64, + db: String, + manifest_server: String, + ) -> bool; +} diff --git a/src/f3/mod.rs b/src/f3/mod.rs new file mode 100644 index 000000000000..8fddaf5dc81f --- /dev/null +++ b/src/f3/mod.rs @@ -0,0 +1,50 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +#[cfg(f3sidecar)] +mod go_ffi; +#[cfg(f3sidecar)] +use go_ffi::*; + +pub fn run_f3_sidecar_if_enabled( + _rpc_endpoint: String, + _f3_rpc_endpoint: String, + _finality: i64, + _db: String, + _manifest_server: String, +) { + if is_sidecar_ffi_enabled() { + #[cfg(f3sidecar)] + { + GoF3NodeImpl::run( + _rpc_endpoint, + _f3_rpc_endpoint, + _finality, + _db, + _manifest_server, + ); + } + } +} + +// Use opt-in mode for now. Consider switching to opt-out mode once F3 is shipped. +fn is_sidecar_ffi_enabled() -> bool { + // Opt-out building the F3 sidecar staticlib + match std::env::var("FOREST_F3_SIDECAR_FFI_ENABLED") { + Ok(value) => { + let enabled = matches!(value.to_lowercase().as_str(), "1" | "true"); + cfg_if::cfg_if! { + if #[cfg(f3sidecar)] { + enabled + } + else { + if enabled { + tracing::error!("Failed to enable F3 sidecar, the forerst binary is not compiled with f3-sidecar Go lib"); + } + false + } + } + } + _ => false, + } +} diff --git a/src/lib.rs b/src/lib.rs index be82e28f0012..94093eba1827 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,7 @@ mod daemon; mod db; mod documentation; mod eth; +mod f3; mod fil_cns; mod genesis; mod health; diff --git a/src/rpc/methods/f3.rs b/src/rpc/methods/f3.rs index eaadf62d2ade..8be77eabdcf0 100644 --- a/src/rpc/methods/f3.rs +++ b/src/rpc/methods/f3.rs @@ -583,7 +583,7 @@ impl RpcMethod<3> for F3Participate { } } -fn get_f3_rpc_endpoint() -> Cow<'static, str> { +pub fn get_f3_rpc_endpoint() -> Cow<'static, str> { if let Ok(host) = std::env::var("FOREST_F3_SIDECAR_RPC_ENDPOINT") { Cow::Owned(host) } else { From 2640a6faf9213e69acf6e49a8a72861cbe42a391 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Thu, 5 Sep 2024 18:29:21 +0800 Subject: [PATCH 2/8] install Go in Dockerfile --- Cargo.toml | 2 ++ Dockerfile | 4 ++++ interop-tests/Cargo.toml | 2 +- src/f3/mod.rs | 8 ++++---- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 59c66465cfdd..58fcf22ba349 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -268,6 +268,8 @@ tokio-console = ["dep:console-subscriber"] tracing-loki = ["dep:tracing-loki"] tracing-chrome = ["dep:tracing-chrome"] +no-f3-sidecar = [] + [[bench]] name = "example-benchmark" harness = false diff --git a/Dockerfile b/Dockerfile index 8a8d92f2a3e6..ce4e9da6b8c4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,10 @@ RUN apt-get update && \ apt-get install --no-install-recommends -y build-essential clang curl git ca-certificates RUN update-ca-certificates +# install Go +RUN curl -sSL https://raw.githubusercontent.com/voidint/g/master/install.sh | bash +RUN "${HOME}/.g/bin/g" install 1.21 && ln -sf "${HOME}/.g/go/bin/go" /usr/local/bin/go && go version + RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path --profile minimal ENV PATH="/root/.cargo/bin:${PATH}" diff --git a/interop-tests/Cargo.toml b/interop-tests/Cargo.toml index a9e8d400ddde..5aaa06da4946 100644 --- a/interop-tests/Cargo.toml +++ b/interop-tests/Cargo.toml @@ -13,7 +13,7 @@ publish = false [dev-dependencies] anyhow = "1" flume = "0.11" -forest-filecoin = { path = "../", default-features = false, features = ["interop-tests-private"] } +forest-filecoin = { path = "../", default-features = false, features = ["interop-tests-private", "no-f3-sidecar"] } futures = "0.3" libipld = { version = "0.16", default-features = false } libp2p = { version = "0.54", default-features = false, features = [ diff --git a/src/f3/mod.rs b/src/f3/mod.rs index 8fddaf5dc81f..c8f4e2547e24 100644 --- a/src/f3/mod.rs +++ b/src/f3/mod.rs @@ -1,9 +1,9 @@ // Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT -#[cfg(f3sidecar)] +#[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] mod go_ffi; -#[cfg(f3sidecar)] +#[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] use go_ffi::*; pub fn run_f3_sidecar_if_enabled( @@ -14,7 +14,7 @@ pub fn run_f3_sidecar_if_enabled( _manifest_server: String, ) { if is_sidecar_ffi_enabled() { - #[cfg(f3sidecar)] + #[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] { GoF3NodeImpl::run( _rpc_endpoint, @@ -34,7 +34,7 @@ fn is_sidecar_ffi_enabled() -> bool { Ok(value) => { let enabled = matches!(value.to_lowercase().as_str(), "1" | "true"); cfg_if::cfg_if! { - if #[cfg(f3sidecar)] { + if #[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] { enabled } else { From 8d798ca8dd04499bc3a73202ad2aa60e820fab41 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Fri, 6 Sep 2024 12:07:12 +0800 Subject: [PATCH 3/8] resolve comments --- .github/workflows/forest.yml | 5 +- Cargo.lock | 139 ++++++++++++------------------ Cargo.toml | 2 +- f3-sidecar/ffi_gen.go | 23 +---- f3-sidecar/ffi_impl.go | 4 +- f3-sidecar/run.go | 4 +- scripts/devnet/docker-compose.yml | 2 +- src/daemon/mod.rs | 29 ++++--- src/f3/go_ffi.rs | 6 +- src/f3/mod.rs | 29 +++---- src/rpc/methods/f3.rs | 15 +++- 11 files changed, 111 insertions(+), 147 deletions(-) diff --git a/.github/workflows/forest.yml b/.github/workflows/forest.yml index 6f735b18f67e..bb513c9be9ec 100644 --- a/.github/workflows/forest.yml +++ b/.github/workflows/forest.yml @@ -100,9 +100,12 @@ jobs: - name: Install Apt Dependencies run: | sudo make install-deps + - uses: actions/setup-go@v5 + with: + go-version-file: "go.work" - run: cargo publish --dry-run env: - FOREST_F3_SIDECAR_FFI_BUILD_OPT_OUT: 1 + GOWORK: off forest-cli-check: needs: - build-ubuntu diff --git a/Cargo.lock b/Cargo.lock index 2d70b425da4f..ae3e4d897d48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -441,7 +441,7 @@ dependencies = [ "futures-lite 2.3.0", "parking", "polling 3.7.3", - "rustix 0.38.35", + "rustix 0.38.36", "slab", "tracing", "windows-sys 0.59.0", @@ -491,7 +491,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.35", + "rustix 0.38.36", "windows-sys 0.48.0", ] @@ -507,7 +507,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.35", + "rustix 0.38.36", "signal-hook-registry", "slab", "windows-sys 0.59.0", @@ -817,16 +817,14 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.69.4" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -835,7 +833,6 @@ dependencies = [ "rustc-hash 1.1.0", "shlex", "syn 2.0.77", - "which", ] [[package]] @@ -1046,9 +1043,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" [[package]] name = "byteorder" @@ -1114,20 +1111,20 @@ dependencies = [ [[package]] name = "cbindgen" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49" +checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" dependencies = [ "heck 0.4.1", - "indexmap 1.9.3", + "indexmap 2.5.0", "log", "proc-macro2", "quote", "serde", "serde_json", - "syn 1.0.109", + "syn 2.0.77", "tempfile", - "toml 0.5.11", + "toml 0.8.19", ] [[package]] @@ -1141,9 +1138,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" dependencies = [ "jobserver", "libc", @@ -1288,9 +1285,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -1298,9 +1295,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -4012,7 +4009,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" dependencies = [ - "rustix 0.38.35", + "rustix 0.38.36", "windows-targets 0.52.6", ] @@ -4334,15 +4331,6 @@ dependencies = [ "hmac 0.8.1", ] -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "hostname" version = "0.3.1" @@ -4493,9 +4481,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" dependencies = [ "futures-util", "http 1.1.0", @@ -5116,12 +5104,6 @@ dependencies = [ "spin 0.9.8", ] -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "leb128" version = "0.2.5" @@ -5944,7 +5926,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "rustix 0.38.35", + "rustix 0.38.36", ] [[package]] @@ -6898,7 +6880,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.35", + "rustix 0.38.36", "tracing", "windows-sys 0.59.0", ] @@ -7092,7 +7074,7 @@ dependencies = [ "hex", "lazy_static", "procfs-core", - "rustix 0.38.35", + "rustix 0.38.36", ] [[package]] @@ -7194,9 +7176,9 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1f9bf148c15500d44581654fb9260bc9d82970f3ef777a79a40534f6aa784f" +checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" dependencies = [ "cc", ] @@ -7263,9 +7245,9 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d2fb862b7ba45e615c1429def928f2e15f815bdf933b27a2d3824e224c1f46" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ "bytes", "futures-io", @@ -7282,9 +7264,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.7" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0a9b3a42929fad8a7c3de7f86ce0814cfa893328157672680e9fb1145549c5" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", "rand", @@ -7299,15 +7281,15 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" dependencies = [ "libc", "once_cell", "socket2 0.5.7", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7764,9 +7746,9 @@ dependencies = [ [[package]] name = "rust2go" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b076f3860d19c2be389d6f7e1d49262b3a8baf27358ffd82ac811d5c4784315f" +checksum = "1fb8398eed0838a26fda0a3eb2228c85e51b0f32206e97e687b8e79b1d34e8c2" dependencies = [ "bindgen", "rust2go-cli", @@ -7777,20 +7759,21 @@ dependencies = [ [[package]] name = "rust2go-cli" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fa35e543b9db7ff7372d4dbe1a3c94cc65d92b07793b7fc47a0e1c88691d35" +checksum = "1f61be8d1dbce9757a3174b7c651b995908af56c3cf4832d0e8809e1653a0f38" dependencies = [ "cbindgen", "clap", + "itertools 0.13.0", "rust2go-common", ] [[package]] name = "rust2go-common" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c571c2056a86d51c57c1c1e908929e46c1c18cd0e5f10adb24ef8dbb0b7ec1" +checksum = "c501dad4b73f3fa62258bed2623cb695f69686a8c304d6b90f807f9b19772fb6" dependencies = [ "proc-macro2", "quote", @@ -7873,9 +7856,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.35" +version = "0.38.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" dependencies = [ "bitflags 2.6.0", "errno", @@ -8177,9 +8160,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -8967,7 +8950,7 @@ dependencies = [ "cfg-if", "fastrand 2.1.1", "once_cell", - "rustix 0.38.35", + "rustix 0.38.36", "windows-sys 0.59.0", ] @@ -9175,9 +9158,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -9200,9 +9183,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -9903,7 +9886,7 @@ dependencies = [ "once_cell", "paste", "rayon", - "rustix 0.38.35", + "rustix 0.38.36", "serde", "serde_derive", "serde_json", @@ -10071,7 +10054,7 @@ dependencies = [ "log", "object 0.31.1", "rustc-demangle", - "rustix 0.38.35", + "rustix 0.38.36", "serde", "target-lexicon", "wasmtime-environ 12.0.2", @@ -10129,7 +10112,7 @@ dependencies = [ "memoffset 0.9.1", "paste", "rand", - "rustix 0.38.35", + "rustix 0.38.36", "sptr", "wasm-encoder 0.31.1", "wasmtime-asm-macros 12.0.2", @@ -10156,7 +10139,7 @@ dependencies = [ "memoffset 0.9.1", "paste", "psm", - "rustix 0.38.35", + "rustix 0.38.36", "sptr", "wasm-encoder 0.201.0", "wasmtime-asm-macros 19.0.2", @@ -10254,18 +10237,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.35", -] - [[package]] name = "wide" version = "0.7.28" @@ -10645,7 +10616,7 @@ checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", "linux-raw-sys 0.4.14", - "rustix 0.38.35", + "rustix 0.38.36", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 58fcf22ba349..2ae95e636ec7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/ChainSafe/forest" edition = "2021" license = "MIT OR Apache-2.0" description = "Rust Filecoin implementation." -exclude = [".config", ".github", ".maintain", "documentation", "scripts", "interop-tests"] +exclude = [".config", ".github", ".maintain", "documentation", "scripts", "interop-tests", "go.work*"] [dependencies] ahash = "0.8" diff --git a/f3-sidecar/ffi_gen.go b/f3-sidecar/ffi_gen.go index 4e8863827a0a..80ed46625709 100644 --- a/f3-sidecar/ffi_gen.go +++ b/f3-sidecar/ffi_gen.go @@ -8,10 +8,6 @@ package main #include #include -typedef struct EmptyReqRef { - -} EmptyReqRef; - typedef struct ListRef { const void *ptr; uintptr_t len; @@ -37,12 +33,12 @@ import ( var GoF3NodeImpl GoF3Node type GoF3Node interface { - run(rpc_endpoint string, f3_rpc_endpoint string, finality int64, db string, manifest_server string) bool + run(rpc_endpoint string, f3_rpc_socket_address string, finality int64, db string, manifest_server string) bool } //export CGoF3Node_run -func CGoF3Node_run(rpc_endpoint C.StringRef, f3_rpc_endpoint C.StringRef, finality C.int64_t, db C.StringRef, manifest_server C.StringRef, slot *C.void, cb *C.void) { - resp := GoF3NodeImpl.run(newString(rpc_endpoint), newString(f3_rpc_endpoint), newC_int64_t(finality), newString(db), newString(manifest_server)) +func CGoF3Node_run(rpc_endpoint C.StringRef, f3_rpc_socket_address C.StringRef, finality C.int64_t, db C.StringRef, manifest_server C.StringRef, slot *C.void, cb *C.void) { + resp := GoF3NodeImpl.run(newString(rpc_endpoint), newString(f3_rpc_socket_address), newC_int64_t(finality), newString(db), newString(manifest_server)) resp_ref, buffer := cvt_ref(cntC_bool, refC_bool)(&resp) C.GoF3Node_run_cb(unsafe.Pointer(cb), resp_ref, unsafe.Pointer(slot)) runtime.KeepAlive(resp) @@ -195,16 +191,3 @@ func refC_uintptr_t(p *uint, _ *[]byte) C.uintptr_t { return C.uintptr_t(*p) } func refC_intptr_t(p *int, _ *[]byte) C.intptr_t { return C.intptr_t(*p) } func refC_float(p *float32, _ *[]byte) C.float { return C.float(*p) } func refC_double(p *float64, _ *[]byte) C.double { return C.double(*p) } - -type EmptyReq struct { -} - -func newEmptyReq(p C.EmptyReqRef) EmptyReq { - return EmptyReq{} -} -func cntEmptyReq(s *EmptyReq, cnt *uint) [0]C.EmptyReqRef { - return [0]C.EmptyReqRef{} -} -func refEmptyReq(p *EmptyReq, buffer *[]byte) C.EmptyReqRef { - return C.EmptyReqRef{} -} diff --git a/f3-sidecar/ffi_impl.go b/f3-sidecar/ffi_impl.go index 6448a43fa6d9..88db730a93a2 100644 --- a/f3-sidecar/ffi_impl.go +++ b/f3-sidecar/ffi_impl.go @@ -21,8 +21,8 @@ type f3Impl struct { ctx context.Context } -func (f3 *f3Impl) run(rpc_endpoint string, f3_rpc_endpoint string, finality int64, db string, manifest_server string) bool { - err := run(f3.ctx, rpc_endpoint, f3_rpc_endpoint, finality, db, manifest_server) +func (f3 *f3Impl) run(rpc_endpoint string, f3_rpc_socket_address string, finality int64, db string, manifest_server string) bool { + err := run(f3.ctx, rpc_endpoint, f3_rpc_socket_address, finality, db, manifest_server) return err == nil } diff --git a/f3-sidecar/run.go b/f3-sidecar/run.go index 8d6ff2256cd7..1bb477a8c13a 100644 --- a/f3-sidecar/run.go +++ b/f3-sidecar/run.go @@ -18,7 +18,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ) -func run(ctx context.Context, rpcEndpoint string, f3RpcEndpoint string, finality int64, db string, manifestServer string) error { +func run(ctx context.Context, rpcEndpoint string, f3RpcSocketAddress string, finality int64, db string, manifestServer string) error { api := FilecoinApi{} closer, err := jsonrpc.NewClient(context.Background(), rpcEndpoint, "Filecoin", &api, nil) if err != nil { @@ -97,7 +97,7 @@ func run(ctx context.Context, rpcEndpoint string, f3RpcEndpoint string, finality srv := &http.Server{ Handler: rpcServer, } - listener, err := net.Listen("tcp", f3RpcEndpoint) + listener, err := net.Listen("tcp", f3RpcSocketAddress) if err != nil { return err } diff --git a/scripts/devnet/docker-compose.yml b/scripts/devnet/docker-compose.yml index 113e77dfa1d9..844055dec1fe 100644 --- a/scripts/devnet/docker-compose.yml +++ b/scripts/devnet/docker-compose.yml @@ -182,7 +182,7 @@ services: - FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE} - RUST_LOG=info,forest_filecoin::blocks::header=trace - FOREST_F3_PERMANENT_PARTICIPATING_MINER_ADDRESSES=${MINER_ACTOR_ADDRESS} - - FOREST_F3_SIDECAR_RPC_ENDPOINT=f3:${F3_RPC_PORT} + - FOREST_F3_SIDECAR_RPC_SOCKET_ADDRESS=f3:${F3_RPC_PORT} - FOREST_GENESIS_NETWORK_VERSION=${GENESIS_NETWORK_VERSION} - FOREST_SHARK_HEIGHT=${SHARK_HEIGHT} - FOREST_HYGGE_HEIGHT=${HYGGE_HEIGHT} diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs index aefa87096615..13e618b4e5d5 100644 --- a/src/daemon/mod.rs +++ b/src/daemon/mod.rs @@ -412,18 +412,23 @@ pub(super) async fn start( .await }); - let finality = chain_config.policy.chain_finality; - let chain = config.chain.to_string(); - services.spawn_blocking(move || { - crate::f3::run_f3_sidecar_if_enabled( - format!("http://{rpc_address}/rpc/v1"), - crate::rpc::f3::get_f3_rpc_endpoint().to_string(), - finality, - std::env::var("FOREST_F3_DB_PATH") - .unwrap_or_else(|_| format!("/var/tmp/f3-db-{chain}")), - std::env::var("FOREST_F3_MANIFEST_SERVER").unwrap_or_default(), - ); - Ok(()) + services.spawn_blocking({ + let finality = chain_config.policy.chain_finality; + let default_f3_db_path = config + .client + .data_dir + .join(format!("/var/tmp/f3-db/{}", config.chain)); + move || { + crate::f3::run_f3_sidecar_if_enabled( + format!("http://{rpc_address}/rpc/v1"), + crate::rpc::f3::get_f3_rpc_socket_addr()?.to_string(), + finality, + std::env::var("FOREST_F3_DB_PATH") + .unwrap_or(default_f3_db_path.display().to_string()), + std::env::var("FOREST_F3_MANIFEST_SERVER").unwrap_or_default(), + ); + Ok(()) + } }); } else { debug!("RPC disabled."); diff --git a/src/f3/go_ffi.rs b/src/f3/go_ffi.rs index 8bbd3a9adccb..ef2602bb597d 100644 --- a/src/f3/go_ffi.rs +++ b/src/f3/go_ffi.rs @@ -3,17 +3,15 @@ pub mod binding { #![allow(warnings)] + #![allow(clippy::indexing_slicing)] rust2go::r2g_include_binding!(); } -#[derive(rust2go::R2G, Clone, Default)] -pub struct EmptyReq {} - #[rust2go::r2g] pub trait GoF3Node { fn run( rpc_endpoint: String, - f3_rpc_endpoint: String, + f3_rpc_socket_address: String, finality: i64, db: String, manifest_server: String, diff --git a/src/f3/mod.rs b/src/f3/mod.rs index c8f4e2547e24..782a92d56eb9 100644 --- a/src/f3/mod.rs +++ b/src/f3/mod.rs @@ -6,9 +6,11 @@ mod go_ffi; #[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] use go_ffi::*; +use crate::utils::misc::env::is_env_truthy; + pub fn run_f3_sidecar_if_enabled( _rpc_endpoint: String, - _f3_rpc_endpoint: String, + _f3_rpc_socket_address: String, _finality: i64, _db: String, _manifest_server: String, @@ -18,7 +20,7 @@ pub fn run_f3_sidecar_if_enabled( { GoF3NodeImpl::run( _rpc_endpoint, - _f3_rpc_endpoint, + _f3_rpc_socket_address, _finality, _db, _manifest_server, @@ -30,21 +32,16 @@ pub fn run_f3_sidecar_if_enabled( // Use opt-in mode for now. Consider switching to opt-out mode once F3 is shipped. fn is_sidecar_ffi_enabled() -> bool { // Opt-out building the F3 sidecar staticlib - match std::env::var("FOREST_F3_SIDECAR_FFI_ENABLED") { - Ok(value) => { - let enabled = matches!(value.to_lowercase().as_str(), "1" | "true"); - cfg_if::cfg_if! { - if #[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] { - enabled - } - else { - if enabled { - tracing::error!("Failed to enable F3 sidecar, the forerst binary is not compiled with f3-sidecar Go lib"); - } - false - } + let enabled = is_env_truthy("FOREST_F3_SIDECAR_FFI_ENABLED"); + cfg_if::cfg_if! { + if #[cfg(all(f3sidecar, not(feature = "no-f3-sidecar")))] { + enabled + } + else { + if enabled { + tracing::error!("Failed to enable F3 sidecar, the forerst binary is not compiled with f3-sidecar Go lib"); } + false } - _ => false, } } diff --git a/src/rpc/methods/f3.rs b/src/rpc/methods/f3.rs index 8be77eabdcf0..5ef7fdb52fbf 100644 --- a/src/rpc/methods/f3.rs +++ b/src/rpc/methods/f3.rs @@ -37,7 +37,13 @@ use libp2p::PeerId; use num::Signed as _; use once_cell::sync::Lazy; use parking_lot::RwLock; -use std::{borrow::Cow, fmt::Display, str::FromStr as _, sync::Arc}; +use std::{ + borrow::Cow, + fmt::Display, + net::{AddrParseError, SocketAddr}, + str::FromStr as _, + sync::Arc, +}; static F3_LEASE_MANAGER: Lazy = Lazy::new(Default::default); @@ -583,16 +589,17 @@ impl RpcMethod<3> for F3Participate { } } -pub fn get_f3_rpc_endpoint() -> Cow<'static, str> { - if let Ok(host) = std::env::var("FOREST_F3_SIDECAR_RPC_ENDPOINT") { +pub fn get_f3_rpc_socket_addr() -> Result { + if let Ok(host) = std::env::var("FOREST_F3_SIDECAR_RPC_SOCKET_ADDRESS") { Cow::Owned(host) } else { Cow::Borrowed("127.0.0.1:23456") } + .parse() } fn get_rpc_http_client() -> anyhow::Result { let client = jsonrpsee::http_client::HttpClientBuilder::new() - .build(format!("http://{}", get_f3_rpc_endpoint()))?; + .build(format!("http://{}", get_f3_rpc_socket_addr()?))?; Ok(client) } From e5e73bcbf04f5cce5180cb91b53c9cddefa95bfb Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Fri, 6 Sep 2024 16:12:05 +0800 Subject: [PATCH 4/8] revert SocketAddr change --- f3-sidecar/ffi_gen.go | 6 +++--- f3-sidecar/ffi_impl.go | 4 ++-- f3-sidecar/run.go | 4 ++-- scripts/devnet/docker-compose.yml | 2 +- src/daemon/mod.rs | 2 +- src/f3/go_ffi.rs | 2 +- src/f3/mod.rs | 4 ++-- src/rpc/methods/f3.rs | 15 ++++----------- 8 files changed, 16 insertions(+), 23 deletions(-) diff --git a/f3-sidecar/ffi_gen.go b/f3-sidecar/ffi_gen.go index 80ed46625709..211a86c3dc9a 100644 --- a/f3-sidecar/ffi_gen.go +++ b/f3-sidecar/ffi_gen.go @@ -33,12 +33,12 @@ import ( var GoF3NodeImpl GoF3Node type GoF3Node interface { - run(rpc_endpoint string, f3_rpc_socket_address string, finality int64, db string, manifest_server string) bool + run(rpc_endpoint string, f3_rpc_endpoint string, finality int64, db string, manifest_server string) bool } //export CGoF3Node_run -func CGoF3Node_run(rpc_endpoint C.StringRef, f3_rpc_socket_address C.StringRef, finality C.int64_t, db C.StringRef, manifest_server C.StringRef, slot *C.void, cb *C.void) { - resp := GoF3NodeImpl.run(newString(rpc_endpoint), newString(f3_rpc_socket_address), newC_int64_t(finality), newString(db), newString(manifest_server)) +func CGoF3Node_run(rpc_endpoint C.StringRef, f3_rpc_endpoint C.StringRef, finality C.int64_t, db C.StringRef, manifest_server C.StringRef, slot *C.void, cb *C.void) { + resp := GoF3NodeImpl.run(newString(rpc_endpoint), newString(f3_rpc_endpoint), newC_int64_t(finality), newString(db), newString(manifest_server)) resp_ref, buffer := cvt_ref(cntC_bool, refC_bool)(&resp) C.GoF3Node_run_cb(unsafe.Pointer(cb), resp_ref, unsafe.Pointer(slot)) runtime.KeepAlive(resp) diff --git a/f3-sidecar/ffi_impl.go b/f3-sidecar/ffi_impl.go index 88db730a93a2..6448a43fa6d9 100644 --- a/f3-sidecar/ffi_impl.go +++ b/f3-sidecar/ffi_impl.go @@ -21,8 +21,8 @@ type f3Impl struct { ctx context.Context } -func (f3 *f3Impl) run(rpc_endpoint string, f3_rpc_socket_address string, finality int64, db string, manifest_server string) bool { - err := run(f3.ctx, rpc_endpoint, f3_rpc_socket_address, finality, db, manifest_server) +func (f3 *f3Impl) run(rpc_endpoint string, f3_rpc_endpoint string, finality int64, db string, manifest_server string) bool { + err := run(f3.ctx, rpc_endpoint, f3_rpc_endpoint, finality, db, manifest_server) return err == nil } diff --git a/f3-sidecar/run.go b/f3-sidecar/run.go index 1bb477a8c13a..8d6ff2256cd7 100644 --- a/f3-sidecar/run.go +++ b/f3-sidecar/run.go @@ -18,7 +18,7 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ) -func run(ctx context.Context, rpcEndpoint string, f3RpcSocketAddress string, finality int64, db string, manifestServer string) error { +func run(ctx context.Context, rpcEndpoint string, f3RpcEndpoint string, finality int64, db string, manifestServer string) error { api := FilecoinApi{} closer, err := jsonrpc.NewClient(context.Background(), rpcEndpoint, "Filecoin", &api, nil) if err != nil { @@ -97,7 +97,7 @@ func run(ctx context.Context, rpcEndpoint string, f3RpcSocketAddress string, fin srv := &http.Server{ Handler: rpcServer, } - listener, err := net.Listen("tcp", f3RpcSocketAddress) + listener, err := net.Listen("tcp", f3RpcEndpoint) if err != nil { return err } diff --git a/scripts/devnet/docker-compose.yml b/scripts/devnet/docker-compose.yml index 844055dec1fe..113e77dfa1d9 100644 --- a/scripts/devnet/docker-compose.yml +++ b/scripts/devnet/docker-compose.yml @@ -182,7 +182,7 @@ services: - FIL_PROOFS_PARAMETER_CACHE=${FIL_PROOFS_PARAMETER_CACHE} - RUST_LOG=info,forest_filecoin::blocks::header=trace - FOREST_F3_PERMANENT_PARTICIPATING_MINER_ADDRESSES=${MINER_ACTOR_ADDRESS} - - FOREST_F3_SIDECAR_RPC_SOCKET_ADDRESS=f3:${F3_RPC_PORT} + - FOREST_F3_SIDECAR_RPC_ENDPOINT=f3:${F3_RPC_PORT} - FOREST_GENESIS_NETWORK_VERSION=${GENESIS_NETWORK_VERSION} - FOREST_SHARK_HEIGHT=${SHARK_HEIGHT} - FOREST_HYGGE_HEIGHT=${HYGGE_HEIGHT} diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs index 13e618b4e5d5..dd7d7ee89403 100644 --- a/src/daemon/mod.rs +++ b/src/daemon/mod.rs @@ -421,7 +421,7 @@ pub(super) async fn start( move || { crate::f3::run_f3_sidecar_if_enabled( format!("http://{rpc_address}/rpc/v1"), - crate::rpc::f3::get_f3_rpc_socket_addr()?.to_string(), + crate::rpc::f3::get_f3_rpc_endpoint().to_string(), finality, std::env::var("FOREST_F3_DB_PATH") .unwrap_or(default_f3_db_path.display().to_string()), diff --git a/src/f3/go_ffi.rs b/src/f3/go_ffi.rs index ef2602bb597d..fbecc861f847 100644 --- a/src/f3/go_ffi.rs +++ b/src/f3/go_ffi.rs @@ -11,7 +11,7 @@ pub mod binding { pub trait GoF3Node { fn run( rpc_endpoint: String, - f3_rpc_socket_address: String, + f3_rpc_endpoint: String, finality: i64, db: String, manifest_server: String, diff --git a/src/f3/mod.rs b/src/f3/mod.rs index 782a92d56eb9..6e62703d3ee1 100644 --- a/src/f3/mod.rs +++ b/src/f3/mod.rs @@ -10,7 +10,7 @@ use crate::utils::misc::env::is_env_truthy; pub fn run_f3_sidecar_if_enabled( _rpc_endpoint: String, - _f3_rpc_socket_address: String, + _f3_rpc_endpoint: String, _finality: i64, _db: String, _manifest_server: String, @@ -20,7 +20,7 @@ pub fn run_f3_sidecar_if_enabled( { GoF3NodeImpl::run( _rpc_endpoint, - _f3_rpc_socket_address, + _f3_rpc_endpoint, _finality, _db, _manifest_server, diff --git a/src/rpc/methods/f3.rs b/src/rpc/methods/f3.rs index 5ef7fdb52fbf..8be77eabdcf0 100644 --- a/src/rpc/methods/f3.rs +++ b/src/rpc/methods/f3.rs @@ -37,13 +37,7 @@ use libp2p::PeerId; use num::Signed as _; use once_cell::sync::Lazy; use parking_lot::RwLock; -use std::{ - borrow::Cow, - fmt::Display, - net::{AddrParseError, SocketAddr}, - str::FromStr as _, - sync::Arc, -}; +use std::{borrow::Cow, fmt::Display, str::FromStr as _, sync::Arc}; static F3_LEASE_MANAGER: Lazy = Lazy::new(Default::default); @@ -589,17 +583,16 @@ impl RpcMethod<3> for F3Participate { } } -pub fn get_f3_rpc_socket_addr() -> Result { - if let Ok(host) = std::env::var("FOREST_F3_SIDECAR_RPC_SOCKET_ADDRESS") { +pub fn get_f3_rpc_endpoint() -> Cow<'static, str> { + if let Ok(host) = std::env::var("FOREST_F3_SIDECAR_RPC_ENDPOINT") { Cow::Owned(host) } else { Cow::Borrowed("127.0.0.1:23456") } - .parse() } fn get_rpc_http_client() -> anyhow::Result { let client = jsonrpsee::http_client::HttpClientBuilder::new() - .build(format!("http://{}", get_f3_rpc_socket_addr()?))?; + .build(format!("http://{}", get_f3_rpc_endpoint()))?; Ok(client) } From 9fc2ba8a0e2c3cecc2c19f18f3702e50aaf27a22 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Fri, 6 Sep 2024 16:29:25 +0800 Subject: [PATCH 5/8] md updates --- README.md | 4 ++++ f3-sidecar/README.md | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 4e526343fe27..ed45d2676664 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,13 @@ tag. ## Dependencies - Rust (toolchain version is specified in `rust-toolchain.toml`) +- Go for building F3 sidecar module. (toolchain version is specified in + `go.work`) Install [rustup](https://rustup.rs/) +Install [Go](https://go.dev/doc/install) + - OS Base-Devel/Build-Essential - Clang compiler diff --git a/f3-sidecar/README.md b/f3-sidecar/README.md index 0be6231797bd..351ff8802588 100644 --- a/f3-sidecar/README.md +++ b/f3-sidecar/README.md @@ -1,3 +1,11 @@ +### Dependencies + +In addition to the Rust toolchain, Go toolchain is required to build the +`f3-sidecar`. The Go version is specified in `go.mod`. + +Follow https://go.dev/doc/install or use one of the version managers of Go. +(e.g. https://github.com/voidint/g?tab=readme-ov-file#installation) + ### EC tests - run a forest node locally and expose RPC port at the default 2345 From 1018b7f98858850d26d00a238cf30e0d82bf0c09 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Fri, 6 Sep 2024 17:16:22 +0800 Subject: [PATCH 6/8] fix f3-db path --- src/daemon/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs index dd7d7ee89403..283c391a8421 100644 --- a/src/daemon/mod.rs +++ b/src/daemon/mod.rs @@ -417,7 +417,7 @@ pub(super) async fn start( let default_f3_db_path = config .client .data_dir - .join(format!("/var/tmp/f3-db/{}", config.chain)); + .join(format!("f3-db/{}", config.chain)); move || { crate::f3::run_f3_sidecar_if_enabled( format!("http://{rpc_address}/rpc/v1"), From 936c448f5244e7674c8d37b10b6d54136352d51f Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Fri, 6 Sep 2024 21:41:02 +0800 Subject: [PATCH 7/8] set GOWORK=off in build.rs --- .github/workflows/forest.yml | 2 -- build.rs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/forest.yml b/.github/workflows/forest.yml index bb513c9be9ec..8fcc5db54b83 100644 --- a/.github/workflows/forest.yml +++ b/.github/workflows/forest.yml @@ -104,8 +104,6 @@ jobs: with: go-version-file: "go.work" - run: cargo publish --dry-run - env: - GOWORK: off forest-cli-check: needs: - build-ubuntu diff --git a/build.rs b/build.rs index 5b494375f858..be75387af6be 100644 --- a/build.rs +++ b/build.rs @@ -9,6 +9,7 @@ fn main() { // No proper version of Go compiler is available. if !is_docs_rs() && is_sidecar_ffi_enabled() { println!("cargo:rustc-cfg=f3sidecar"); + std::env::set_var("GOWORK", "off"); rust2go::Builder::default() .with_go_src("./f3-sidecar") .with_regen_arg(rust2go::RegenArgs { From bb05630a6805d04665be436e46d86519cf614f0b Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 11 Sep 2024 15:33:00 +0800 Subject: [PATCH 8/8] Opt out F3 sidecar build in Dockerfile --- Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index ab02b20cedb5..5b05e7aa2dab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,10 +30,6 @@ RUN apt-get update && \ apt-get install --no-install-recommends -y build-essential clang curl git ca-certificates RUN update-ca-certificates -# install Go -RUN curl -sSL https://raw.githubusercontent.com/voidint/g/master/install.sh | bash -RUN "${HOME}/.g/bin/g" install 1.21 && ln -sf "${HOME}/.g/go/bin/go" /usr/local/bin/go && go version - RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path --profile minimal ENV PATH="/root/.cargo/bin:${PATH}" @@ -50,6 +46,9 @@ RUN xx-apt-get update && \ WORKDIR /forest COPY . . +# TODO(forest): https://github.com/ChainSafe/forest/issues/4758 +ENV FOREST_F3_SIDECAR_FFI_BUILD_OPT_OUT=1 + # Install Forest. Move it out of the cache for the prod image. RUN --mount=type=cache,sharing=private,target=/root/.cargo/registry \ --mount=type=cache,sharing=private,target=/root/.rustup \