From 5fc397c2ee59a4ca6feb7201eb13b6f79915fa4c Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Mon, 13 Apr 2026 15:53:31 +0300 Subject: [PATCH] fix: ci fix --- Cargo.lock | 12 -- Cargo.toml | 2 +- indexer_ffi/src/indexer.rs | 39 +++-- indexer_service_ffi/Cargo.toml | 17 --- indexer_service_ffi/src/main.rs | 37 ----- integration_tests/src/test_context_ffi.rs | 169 +++++++++++----------- integration_tests/tests/indexer.rs | 23 +-- 7 files changed, 120 insertions(+), 179 deletions(-) delete mode 100644 indexer_service_ffi/Cargo.toml delete mode 100644 indexer_service_ffi/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index e5efdd6f..898dabfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3487,18 +3487,6 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "indexer_service_ffi" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "env_logger", - "indexer_ffi", - "log", - "tokio", -] - [[package]] name = "indexer_service_protocol" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 4ae2e09b..0ea4f614 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,7 @@ members = [ "examples/program_deployment/methods/guest", "bedrock_client", "testnet_initial_state", - "indexer_ffi", "indexer_service_ffi", + "indexer_ffi", ] [workspace.dependencies] diff --git a/indexer_ffi/src/indexer.rs b/indexer_ffi/src/indexer.rs index 0cd0c980..a3991388 100644 --- a/indexer_ffi/src/indexer.rs +++ b/indexer_ffi/src/indexer.rs @@ -18,36 +18,51 @@ impl IndexerServiceFFI { } } - // Helper to safely take ownership back + /// Helper to take ownership back. + /// + /// # Safety + /// + /// The caller must ensure that: + /// - `self` is a valid object(contains valid pointers in all fields) #[must_use] - pub fn into_parts(self) -> (Box, Box) { + pub unsafe fn into_parts(self) -> (Box, Box) { let indexer_handle = unsafe { Box::from_raw(self.indexer_handle.cast::()) }; let runtime = unsafe { Box::from_raw(self.runtime.cast::()) }; (indexer_handle, runtime) } - // Helper to get indexer handle addr - pub unsafe fn addr(&self) -> SocketAddr { + /// Helper to get indexer handle addr. + /// + /// # Safety + /// + /// The caller must ensure that: + /// - `self` is a valid object(contains valid pointers in all fields) + #[must_use] + pub const unsafe fn addr(&self) -> SocketAddr { let indexer_handle = unsafe { self.indexer_handle .cast::() .as_ref() - .expect("Indexr Handle must be non-null pointer") + .expect("Indexer Handle must be non-null pointer") }; indexer_handle.addr() } - // Helper to get indexer handle addr - pub unsafe fn handle(&self) -> &IndexerHandle { - let indexer_handle = unsafe { + /// Helper to get indexer handle addr. + /// + /// # Safety + /// + /// The caller must ensure that: + /// - `self` is a valid object(contains valid pointers in all fields) + #[must_use] + pub const unsafe fn handle(&self) -> &IndexerHandle { + unsafe { self.indexer_handle .cast::() .as_ref() - .expect("Indexr Handle must be non-null pointer") - }; - - indexer_handle + .expect("Indexer Handle must be non-null pointer") + } } } diff --git a/indexer_service_ffi/Cargo.toml b/indexer_service_ffi/Cargo.toml deleted file mode 100644 index 5d1cfabc..00000000 --- a/indexer_service_ffi/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "indexer_service_ffi" -version = "0.1.0" -edition = "2024" -license.workspace = true - -[dependencies] -indexer_ffi.workspace = true - -log.workspace = true -clap.workspace = true -anyhow.workspace = true -tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] } -env_logger.workspace = true - -[lints] -workspace = true diff --git a/indexer_service_ffi/src/main.rs b/indexer_service_ffi/src/main.rs deleted file mode 100644 index 1aaefdd2..00000000 --- a/indexer_service_ffi/src/main.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::{ffi::{CString, c_char}, path::PathBuf}; - -use anyhow::Result; -use clap::Parser; -use indexer_ffi::api::lifecycle::InitializedIndexerServiceFFIResult; -use log::info; - -#[derive(Debug, Parser)] -#[clap(version)] -struct Args { - #[clap(name = "config")] - config_path: PathBuf, - #[clap(short, long, default_value = "8779")] - port: u16, -} - -unsafe extern "C" { - fn start_indexer(config_path: *const c_char, port: u16) -> InitializedIndexerServiceFFIResult; -} - -fn main() -> Result<()> { - env_logger::init(); - - let Args { config_path, port } = Args::parse(); - - let res = - unsafe { start_indexer(CString::new(config_path.to_str().unwrap())?.as_ptr(), port) }; - - if res.error.is_error() { - anyhow::bail!("Indexer FFI error {:?}", res.error); - } - - loop { - std::thread::sleep(std::time::Duration::from_secs(10)); - info!("Running..."); - } -} diff --git a/integration_tests/src/test_context_ffi.rs b/integration_tests/src/test_context_ffi.rs index f9f37c69..2c5e688d 100644 --- a/integration_tests/src/test_context_ffi.rs +++ b/integration_tests/src/test_context_ffi.rs @@ -1,21 +1,25 @@ use std::{ - ffi::{CString, c_char}, fs::File, io::Write, net::SocketAddr, path::PathBuf, sync::Arc + ffi::{CString, c_char}, + fs::File, + io::Write as _, + net::SocketAddr, + path::PathBuf, + sync::Arc, }; -use anyhow::{Context, Result, bail}; -use futures::FutureExt; +use anyhow::{Context as _, Result, bail}; +use futures::FutureExt as _; use indexer_ffi::{IndexerServiceFFI, api::lifecycle::InitializedIndexerServiceFFIResult}; +use indexer_service_rpc::RpcClient as _; use log::{debug, error, warn}; use nssa::AccountId; -use sequencer_core::indexer_client::{IndexerClient, IndexerClientTrait}; +use sequencer_core::indexer_client::{IndexerClient, IndexerClientTrait as _}; use sequencer_service::SequencerHandle; use sequencer_service_rpc::{RpcClient as _, SequencerClient, SequencerClientBuilder}; use tempfile::TempDir; use testcontainers::compose::DockerCompose; use wallet::{WalletCore, config::WalletConfigOverrides}; -use indexer_service_rpc::RpcClient as _; - use crate::{ BEDROCK_SERVICE_PORT, BEDROCK_SERVICE_WITH_OPEN_PORT, LOGGER, TestContextBuilder, config, }; @@ -36,18 +40,24 @@ pub struct TestContextFFI { wallet_password: String, /// Optional to move out value in Drop. sequencer_handle: Option, - indexer_ffi: IndexerServiceFFI, bedrock_compose: DockerCompose, _temp_indexer_dir: TempDir, _temp_sequencer_dir: TempDir, _temp_wallet_dir: TempDir, } +#[expect( + clippy::multiple_inherent_impl, + reason = "It is more natural to have this implementation here" +)] impl TestContextBuilder { - pub fn build_ffi(self, runtime: Arc) -> Result { + pub fn build_ffi( + self, + runtime: &Arc, + ) -> Result<(TestContextFFI, IndexerServiceFFI)> { TestContextFFI::new_configured( self.sequencer_partial_config.unwrap_or_default(), - self.initial_data.unwrap_or_else(|| { + &self.initial_data.unwrap_or_else(|| { config::InitialData::with_two_public_and_two_private_initialized_accounts() }), runtime, @@ -57,7 +67,7 @@ impl TestContextBuilder { impl TestContextFFI { /// Create new test context. - pub fn new(runtime: Arc) -> Result { + pub fn new(runtime: &Arc) -> Result<(Self, IndexerServiceFFI)> { Self::builder().build_ffi(runtime) } @@ -68,72 +78,62 @@ impl TestContextFFI { fn new_configured( sequencer_partial_config: config::SequencerPartialConfig, - initial_data: config::InitialData, - runtime: Arc - ) -> Result { + initial_data: &config::InitialData, + runtime: &Arc, + ) -> Result<(Self, IndexerServiceFFI)> { // Ensure logger is initialized only once *LOGGER; debug!("Test context setup"); - println!("Hello 3"); - - runtime.block_on(async { println!("Hello 3.5") }); - - println!("Hello 4"); - let (bedrock_compose, bedrock_addr) = runtime.block_on(Self::setup_bedrock_node())?; - println!("Hello 5"); - - let (indexer_ffi, temp_indexer_dir) = Self::setup_indexer_ffi(bedrock_addr, &initial_data) + let (indexer_ffi, temp_indexer_dir) = Self::setup_indexer_ffi(bedrock_addr, initial_data) .context("Failed to setup Indexer")?; - println!("Hello 6"); + let (sequencer_handle, temp_sequencer_dir) = runtime + .block_on(Self::setup_sequencer( + sequencer_partial_config, + bedrock_addr, + // SAFETY: addr is valid if indexer_ffi is valid. + unsafe { indexer_ffi.addr() }, + initial_data, + )) + .context("Failed to setup Sequencer")?; - let (sequencer_handle, temp_sequencer_dir) = runtime.block_on(Self::setup_sequencer( - sequencer_partial_config, - bedrock_addr, - unsafe { indexer_ffi.addr() }, - &initial_data, - )) - .context("Failed to setup Sequencer")?; - - println!("Hello 7"); - - let (wallet, temp_wallet_dir, wallet_password) = - runtime.block_on(Self::setup_wallet(sequencer_handle.addr(), &initial_data) - ) - .context("Failed to setup wallet")?; - - println!("Hello 8"); + let (wallet, temp_wallet_dir, wallet_password) = runtime + .block_on(Self::setup_wallet(sequencer_handle.addr(), initial_data)) + .context("Failed to setup wallet")?; let sequencer_url = config::addr_to_url(config::UrlProtocol::Http, sequencer_handle.addr()) .context("Failed to convert sequencer addr to URL")?; - let indexer_url = - config::addr_to_url(config::UrlProtocol::Ws, unsafe { indexer_ffi.addr() }) - .context("Failed to convert indexer addr to URL")?; + let indexer_url = config::addr_to_url( + config::UrlProtocol::Ws, + // SAFETY: addr is valid if indexer_ffi is valid. + unsafe { indexer_ffi.addr() }, + ) + .context("Failed to convert indexer addr to URL")?; let sequencer_client = SequencerClientBuilder::default() .build(sequencer_url) .context("Failed to create sequencer client")?; - let indexer_client = runtime.block_on(IndexerClient::new(&indexer_url) -) + let indexer_client = runtime + .block_on(IndexerClient::new(&indexer_url)) .context("Failed to create indexer client")?; - println!("Hello 9"); - - Ok(Self { - sequencer_client, - indexer_client, - wallet, - wallet_password, - bedrock_compose, - sequencer_handle: Some(sequencer_handle), + Ok(( + Self { + sequencer_client, + indexer_client, + wallet, + wallet_password, + bedrock_compose, + sequencer_handle: Some(sequencer_handle), + _temp_indexer_dir: temp_indexer_dir, + _temp_sequencer_dir: temp_sequencer_dir, + _temp_wallet_dir: temp_wallet_dir, + }, indexer_ffi, - _temp_indexer_dir: temp_indexer_dir, - _temp_sequencer_dir: temp_sequencer_dir, - _temp_wallet_dir: temp_wallet_dir, - }) + )) } async fn setup_bedrock_node() -> Result<(DockerCompose, SocketAddr)> { @@ -233,13 +233,18 @@ impl TestContextFFI { file.flush()?; let res = + // SAFETY: lib function ensures validity of value. unsafe { start_indexer(CString::new(config_path.to_str().unwrap())?.as_ptr(), 0) }; if res.error.is_error() { anyhow::bail!("Indexer FFI error {:?}", res.error); } - Ok((unsafe { std::ptr::read(res.value) }, temp_indexer_dir)) + Ok(( + // SAFETY: lib function ensures validity of value. + unsafe { std::ptr::read(res.value) }, + temp_indexer_dir, + )) } async fn setup_sequencer( @@ -353,14 +358,11 @@ impl TestContextFFI { .collect() } - pub fn get_last_block_sequencer(&self, runtime: Arc) -> Result { - let res = runtime.block_on(self.sequencer_client.get_last_block_id()).unwrap(); - - println!("Hello 11.5"); - Ok(res) + pub fn get_last_block_sequencer(&self, runtime: &Arc) -> Result { + Ok(runtime.block_on(self.sequencer_client.get_last_block_id())?) } - pub fn get_last_block_indexer(&self, runtime: Arc) -> Result { + pub fn get_last_block_indexer(&self, runtime: &Arc) -> Result { Ok(runtime.block_on(self.indexer_client.get_last_finalized_block_id())?) } } @@ -369,7 +371,6 @@ impl Drop for TestContextFFI { fn drop(&mut self) { let Self { sequencer_handle, - indexer_ffi, bedrock_compose, _temp_indexer_dir: _, _temp_sequencer_dir: _, @@ -393,16 +394,6 @@ impl Drop for TestContextFFI { ); } - println!("Hello 14"); - - let indexer_handle = unsafe { indexer_ffi.handle() }; - - if !indexer_handle.is_healthy() { - error!("Indexer handle has unexpectedly stopped before TestContext drop"); - } - - println!("Hello 15"); - let container = bedrock_compose .service(BEDROCK_SERVICE_WITH_OPEN_PORT) .unwrap_or_else(|| { @@ -420,8 +411,6 @@ impl Drop for TestContextFFI { container.id() ); } - - println!("Hello 16"); } } @@ -429,33 +418,39 @@ impl Drop for TestContextFFI { pub struct BlockingTestContextFFI { ctx: Option, runtime: Arc, + indexer_ffi: IndexerServiceFFI, } impl BlockingTestContextFFI { pub fn new() -> Result { let runtime = tokio::runtime::Runtime::new().unwrap(); let runtime_wrapped = Arc::new(runtime); - let ctx = TestContextFFI::new(runtime_wrapped.clone())?; + let (ctx, indexer_ffi) = TestContextFFI::new(&runtime_wrapped)?; Ok(Self { ctx: Some(ctx), runtime: runtime_wrapped, + indexer_ffi, }) } + #[must_use] pub const fn ctx(&self) -> &TestContextFFI { self.ctx.as_ref().expect("TestContext is set") } - pub fn runtime(&self) -> Arc { - self.runtime.clone() + #[must_use] + pub const fn runtime(&self) -> &Arc { + &self.runtime } } impl Drop for BlockingTestContextFFI { fn drop(&mut self) { - let Self { ctx, runtime } = self; - - println!("Hello 20"); + let Self { + ctx, + runtime, + indexer_ffi, + } = self; // Ensure async cleanup of TestContext by blocking on its drop in the runtime. runtime.block_on(async { @@ -464,6 +459,12 @@ impl Drop for BlockingTestContextFFI { } }); - println!("Hello 21"); + let indexer_handle = + // SAFETY: lib function ensures validity of value. + unsafe { indexer_ffi.handle() }; + + if !indexer_handle.is_healthy() { + error!("Indexer handle has unexpectedly stopped before TestContext drop"); + } } } diff --git a/integration_tests/tests/indexer.rs b/integration_tests/tests/indexer.rs index e71cb132..60b596a7 100644 --- a/integration_tests/tests/indexer.rs +++ b/integration_tests/tests/indexer.rs @@ -7,7 +7,10 @@ use std::time::Duration; use anyhow::Result; use indexer_service_rpc::RpcClient as _; -use integration_tests::{TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, format_public_account_id, test_context_ffi::BlockingTestContextFFI}; +use integration_tests::{ + TIME_TO_WAIT_FOR_BLOCK_SECONDS, TestContext, format_public_account_id, + test_context_ffi::BlockingTestContextFFI, +}; use log::info; use wallet::cli::{Command, programs::native_token_transfer::AuthTransferSubcommand}; @@ -149,29 +152,17 @@ async fn indexer_state_consistency() -> Result<()> { #[test] fn indexer_test_run_ffi() -> Result<()> { - println!("Hello 1"); let blocking_ctx = BlockingTestContextFFI::new()?; let runtime_wrapped = blocking_ctx.runtime(); - log::info!("Hello 3"); - // RUN OBSERVATION runtime_wrapped.block_on(async { tokio::time::sleep(std::time::Duration::from_millis(L2_TO_L1_TIMEOUT_MILLIS)).await; }); - println!("Hello 11"); - - let last_block_seq = blocking_ctx.ctx().get_last_block_sequencer(runtime_wrapped.clone())?; - - println!("Hello 12"); - - let last_block_indexer = blocking_ctx.ctx().get_last_block_indexer(runtime_wrapped)?; - - println!("Hello 13"); - - println!("Last block on ind now is {last_block_indexer}"); - println!("Last block on seq now is {last_block_seq}"); + let last_block_indexer = blocking_ctx + .ctx() + .get_last_block_indexer(runtime_wrapped)?; assert!(last_block_indexer > 1);