From 06a6983ef355d611686a01aa0f36bf8fc2a06385 Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Wed, 29 Apr 2026 17:24:00 +0300 Subject: [PATCH] fix: tests updated --- Cargo.lock | 1 + indexer_ffi/src/api/types/account.rs | 1 + indexer_ffi/src/api/types/mod.rs | 11 ++++ indexer_ffi/src/indexer.rs | 2 +- integration_tests/Cargo.toml | 1 + integration_tests/tests/indexer_ffi.rs | 91 ++++++++++++++++++-------- 6 files changed, 77 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 27831459..8defea3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3606,6 +3606,7 @@ dependencies = [ "hex", "indexer_ffi", "indexer_service", + "indexer_service_protocol", "indexer_service_rpc", "key_protocol", "log", diff --git a/indexer_ffi/src/api/types/account.rs b/indexer_ffi/src/api/types/account.rs index 853e44d4..7893657b 100644 --- a/indexer_ffi/src/api/types/account.rs +++ b/indexer_ffi/src/api/types/account.rs @@ -7,6 +7,7 @@ use crate::api::types::{FfiBytes32, FfiProgramId, FfiU128}; /// Note: `balance` and `nonce` are u128 values represented as little-endian /// byte arrays since C doesn't have native u128 support. #[repr(C)] +#[derive(Clone)] pub struct FfiAccount { pub program_owner: FfiProgramId, /// Balance as little-endian [u8; 16]. diff --git a/indexer_ffi/src/api/types/mod.rs b/indexer_ffi/src/api/types/mod.rs index 22b44c88..2e7a77ad 100644 --- a/indexer_ffi/src/api/types/mod.rs +++ b/indexer_ffi/src/api/types/mod.rs @@ -130,6 +130,17 @@ impl From> for Vec { } } +impl FfiVec { + /// # Safety + /// + /// `index` must be lesser than `self.len`. + #[must_use] + pub unsafe fn get(&self, index: usize) -> &T { + let ptr = unsafe { self.entries.add(index) }; + unsafe { &*ptr } + } +} + #[repr(C)] pub struct FfiOption { pub value: *mut T, diff --git a/indexer_ffi/src/indexer.rs b/indexer_ffi/src/indexer.rs index 102900f6..c64708db 100644 --- a/indexer_ffi/src/indexer.rs +++ b/indexer_ffi/src/indexer.rs @@ -126,6 +126,6 @@ impl Drop for IndexerServiceFFI { } drop(unsafe { Box::from_raw(indexer_handle.cast::()) }); drop(unsafe { Box::from_raw(runtime.cast::()) }); - drop(unsafe { Box::from_raw(indexer_client.cast::()) }); + drop(unsafe { Box::from_raw(indexer_client.cast::()) }); } } diff --git a/integration_tests/Cargo.toml b/integration_tests/Cargo.toml index 53f0ee98..465ff301 100644 --- a/integration_tests/Cargo.toml +++ b/integration_tests/Cargo.toml @@ -24,6 +24,7 @@ sequencer_service_rpc = { workspace = true, features = ["client"] } wallet-ffi.workspace = true indexer_ffi.workspace = true testnet_initial_state.workspace = true +indexer_service_protocol.workspace = true url.workspace = true diff --git a/integration_tests/tests/indexer_ffi.rs b/integration_tests/tests/indexer_ffi.rs index d0c643f7..8ac74ee6 100644 --- a/integration_tests/tests/indexer_ffi.rs +++ b/integration_tests/tests/indexer_ffi.rs @@ -6,8 +6,13 @@ )] use anyhow::{Context as _, Result}; -use indexer_ffi::{IndexerServiceFFI, OperationStatus, api::PointerResult}; -use indexer_service_rpc::RpcClient as _; +use indexer_ffi::{ + IndexerServiceFFI, OperationStatus, + api::{ + PointerResult, + types::{FfiAccountId, FfiOption, FfiVec, account::FfiAccount, block::FfiBlock}, + }, +}; use integration_tests::{ TIME_TO_WAIT_FOR_BLOCK_SECONDS, format_private_account_id, format_public_account_id, test_context_ffi::BlockingTestContextFFI, verify_commitment_is_in_state, @@ -23,6 +28,17 @@ unsafe extern "C" { unsafe fn query_last_block( indexer: *const IndexerServiceFFI, ) -> PointerResult; + + unsafe fn query_block_vec( + indexer: *const IndexerServiceFFI, + before: FfiOption, + limit: u64, + ) -> PointerResult, OperationStatus>; + + unsafe fn query_account( + indexer: *const IndexerServiceFFI, + account_id: FfiAccountId, + ) -> PointerResult; } #[test] @@ -57,7 +73,6 @@ fn indexer_test_run_ffi() -> Result<()> { fn indexer_ffi_block_batching() -> Result<()> { let blocking_ctx = BlockingTestContextFFI::new()?; let runtime_wrapped = blocking_ctx.runtime(); - let ctx = blocking_ctx.ctx(); // WAIT info!("Waiting for indexer to parse blocks"); @@ -65,31 +80,36 @@ fn indexer_ffi_block_batching() -> Result<()> { tokio::time::sleep(std::time::Duration::from_millis(L2_TO_L1_TIMEOUT_MILLIS)).await; }); - let last_block_indexer = runtime_wrapped - .block_on(ctx.indexer_client().get_last_finalized_block_id()) - .unwrap(); + let last_block_indexer_ffi_res = unsafe { query_last_block(blocking_ctx.indexer_ffi()) }; + + assert!(last_block_indexer_ffi_res.error.is_ok()); + + let last_block_indexer = unsafe { *last_block_indexer_ffi_res.value }; info!("Last block on ind now is {last_block_indexer}"); assert!(last_block_indexer > 1); - // Getting wide batch to fit all blocks (from latest backwards) - let mut block_batch = runtime_wrapped - .block_on(ctx.indexer_client().get_blocks(None, 100)) - .unwrap(); + let before_ffi = FfiOption::::from_none(); + let limit = 100; - // Reverse to check chain consistency from oldest to newest - block_batch.reverse(); + let block_batch_ffi_res = + unsafe { query_block_vec(blocking_ctx.indexer_ffi(), before_ffi, limit) }; - // Checking chain consistency - let mut prev_block_hash = block_batch.first().unwrap().header.hash; + assert!(block_batch_ffi_res.error.is_ok()); - for block in &block_batch[1..] { - assert_eq!(block.header.prev_block_hash, prev_block_hash); + let block_batch = unsafe { &*block_batch_ffi_res.value }; + + let mut last_block_prev_hash = unsafe { block_batch.get(0) }.header.prev_block_hash.data; + + for i in 1..block_batch.len { + let block = unsafe { block_batch.get(i) }; + + assert_eq!(last_block_prev_hash, block.header.hash.data); info!("Block {} chain-consistent", block.header.block_id); - prev_block_hash = block.header.hash; + last_block_prev_hash = block.header.prev_block_hash.data; } Ok(()) @@ -99,6 +119,7 @@ fn indexer_ffi_block_batching() -> Result<()> { fn indexer_ffi_state_consistency() -> Result<()> { let mut blocking_ctx = BlockingTestContextFFI::new()?; let runtime_wrapped = blocking_ctx.runtime_clone(); + let indexer_ffi = blocking_ctx.indexer_ffi(); let ctx = blocking_ctx.ctx_mut(); let command = Command::AuthTransfer(AuthTransferSubcommand::Send { @@ -190,14 +211,21 @@ fn indexer_ffi_state_consistency() -> Result<()> { tokio::time::sleep(std::time::Duration::from_millis(L2_TO_L1_TIMEOUT_MILLIS)).await; }); - let acc1_ind_state = runtime_wrapped.block_on( - ctx.indexer_client() - .get_account(ctx.existing_public_accounts()[0].into()), - )?; - let acc2_ind_state = runtime_wrapped.block_on( - ctx.indexer_client() - .get_account(ctx.existing_public_accounts()[1].into()), - )?; + let acc1_ind_state_ffi = + unsafe { query_account(indexer_ffi, (&ctx.existing_public_accounts()[0]).into()) }; + + assert!(acc1_ind_state_ffi.error.is_ok()); + + let acc1_ind_state_pre = unsafe { &*acc1_ind_state_ffi.value }.clone(); + let acc1_ind_state: indexer_service_protocol::Account = acc1_ind_state_pre.into(); + + let acc2_ind_state_ffi = + unsafe { query_account(indexer_ffi, (&ctx.existing_public_accounts()[1]).into()) }; + + assert!(acc2_ind_state_ffi.error.is_ok()); + + let acc2_ind_state_pre = unsafe { &*acc2_ind_state_ffi.value }.clone(); + let acc2_ind_state: indexer_service_protocol::Account = acc2_ind_state_pre.into(); info!("Checking correct state transition"); let acc1_seq_state = @@ -223,6 +251,7 @@ fn indexer_ffi_state_consistency() -> Result<()> { fn indexer_ffi_state_consistency_with_labels() -> Result<()> { let mut blocking_ctx = BlockingTestContextFFI::new()?; let runtime_wrapped = blocking_ctx.runtime_clone(); + let indexer_ffi = blocking_ctx.indexer_ffi(); let ctx = blocking_ctx.ctx_mut(); // Assign labels to both accounts @@ -283,10 +312,14 @@ fn indexer_ffi_state_consistency_with_labels() -> Result<()> { tokio::time::sleep(std::time::Duration::from_millis(L2_TO_L1_TIMEOUT_MILLIS)).await; }); - let acc1_ind_state = runtime_wrapped.block_on( - ctx.indexer_client() - .get_account(ctx.existing_public_accounts()[0].into()), - )?; + let acc1_ind_state_ffi = + unsafe { query_account(indexer_ffi, (&ctx.existing_public_accounts()[0]).into()) }; + + assert!(acc1_ind_state_ffi.error.is_ok()); + + let acc1_ind_state_pre = unsafe { &*acc1_ind_state_ffi.value }.clone(); + let acc1_ind_state: indexer_service_protocol::Account = acc1_ind_state_pre.into(); + let acc1_seq_state = runtime_wrapped.block_on(sequencer_service_rpc::RpcClient::get_account( ctx.sequencer_client(),