From 89ea8842071b8e2450c97c8f2230ae378f94223c Mon Sep 17 00:00:00 2001 From: Pravdyvy Date: Tue, 28 Apr 2026 19:36:23 +0300 Subject: [PATCH] feat: working queries --- Cargo.lock | 2 +- indexer_ffi/Cargo.toml | 2 +- indexer_ffi/indexer_ffi.h | 261 +++++++++++++++++++++- indexer_ffi/src/api/convert.rs | 16 -- indexer_ffi/src/api/lifecycle.rs | 2 +- indexer_ffi/src/api/mod.rs | 1 - indexer_ffi/src/api/query.rs | 16 +- indexer_ffi/src/api/types/account.rs | 40 +--- indexer_ffi/src/api/types/block.rs | 48 +++- indexer_ffi/src/api/types/mod.rs | 75 ++++++- indexer_ffi/src/api/types/transaction.rs | 224 +++++++++++++++++-- indexer_ffi/src/api/types/vectors.rs | 31 +++ integration_tests/src/test_context_ffi.rs | 2 +- integration_tests/tests/indexer_ffi.rs | 1 + 14 files changed, 618 insertions(+), 103 deletions(-) delete mode 100644 indexer_ffi/src/api/convert.rs create mode 100644 indexer_ffi/src/api/types/vectors.rs diff --git a/Cargo.lock b/Cargo.lock index 6517f789..37ab61e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3484,10 +3484,10 @@ version = "0.1.0" dependencies = [ "cbindgen", "indexer_service", + "indexer_service_protocol", "indexer_service_rpc", "log", "nssa", - "nssa_core", "sequencer_core", "tokio", "url", diff --git a/indexer_ffi/Cargo.toml b/indexer_ffi/Cargo.toml index 425e322a..0a140d19 100644 --- a/indexer_ffi/Cargo.toml +++ b/indexer_ffi/Cargo.toml @@ -5,11 +5,11 @@ name = "indexer_ffi" version = "0.1.0" [dependencies] -nssa_core.workspace = true nssa.workspace = true indexer_service.workspace = true sequencer_core.workspace = true indexer_service_rpc.workspace = true +indexer_service_protocol.workspace = true url.workspace = true log = { workspace = true } diff --git a/indexer_ffi/indexer_ffi.h b/indexer_ffi/indexer_ffi.h index cce80837..1094e1de 100644 --- a/indexer_ffi/indexer_ffi.h +++ b/indexer_ffi/indexer_ffi.h @@ -10,6 +10,18 @@ typedef enum OperationStatus { ClientError = 3, } OperationStatus; +typedef enum FfiTransactionKind { + Public = 0, + Private, + ProgramDeploy, +} FfiTransactionKind; + +typedef enum FfiBedrockStatus { + Pending = 0, + Safe, + Finalized, +} FfiBedrockStatus; + typedef struct IndexerServiceFFI { void *indexer_handle; void *runtime; @@ -40,16 +52,255 @@ typedef struct PointerResult_u64__OperationStatus { enum OperationStatus error; } PointerResult_u64__OperationStatus; +typedef uint64_t FfiBlockId; + +/** + * 32-byte array type for `AccountId`, keys, hashes, etc. + */ +typedef struct FfiBytes32 { + uint8_t data[32]; +} FfiBytes32; + +typedef struct FfiBytes32 FfiHashType; + +typedef uint64_t FfiTimestamp; + +/** + * 64-byte array type for signatures, etc. + */ +typedef struct FfiBytes64 { + uint8_t data[64]; +} FfiBytes64; + +typedef struct FfiBytes64 FfiSignature; + +typedef struct FfiBlockHeader { + FfiBlockId block_id; + FfiHashType prev_block_hash; + FfiHashType hash; + FfiTimestamp timestamp; + FfiSignature signature; +} FfiBlockHeader; + +/** + * Program ID - 8 u32 values (32 bytes total). + */ +typedef struct FfiProgramId { + uint32_t data[8]; +} FfiProgramId; + +typedef struct FfiBytes32 FfiAccountId; + +typedef struct FfiVec_FfiAccountId { + FfiAccountId *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiAccountId; + +typedef struct FfiVec_FfiAccountId FfiAccountIdList; + +/** + * U128 - 16 bytes little endian. + */ +typedef struct FfiU128 { + uint8_t data[16]; +} FfiU128; + +typedef struct FfiU128 FfiNonce; + +typedef struct FfiVec_FfiNonce { + FfiNonce *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiNonce; + +typedef struct FfiVec_FfiNonce FfiNonceList; + +typedef struct FfiVec_u32 { + uint32_t *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_u32; + +typedef struct FfiVec_u32 FfiInstructionDataList; + +typedef struct FfiPublicMessage { + struct FfiProgramId program_id; + FfiAccountIdList account_ids; + FfiNonceList nonces; + FfiInstructionDataList instruction_data; +} FfiPublicMessage; + +typedef struct FfiBytes32 FfiPublicKey; + +typedef struct FfiSignaturePubKeyEntry { + FfiSignature signature; + FfiPublicKey public_key; +} FfiSignaturePubKeyEntry; + +typedef struct FfiVec_FfiSignaturePubKeyEntry { + struct FfiSignaturePubKeyEntry *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiSignaturePubKeyEntry; + +typedef struct FfiVec_FfiSignaturePubKeyEntry FfiSignaturePubKeyList; + +typedef struct FfiPublicTransactionBody { + FfiHashType hash; + struct FfiPublicMessage message; + FfiSignaturePubKeyList witness_set; +} FfiPublicTransactionBody; + +/** + * Account data structure - C-compatible version of nssa Account. + * + * Note: `balance` and `nonce` are u128 values represented as little-endian + * byte arrays since C doesn't have native u128 support. + */ +typedef struct FfiAccount { + struct FfiProgramId program_owner; + /** + * Balance as little-endian [u8; 16]. + */ + struct FfiU128 balance; + /** + * Pointer to account data bytes. + */ + const uint8_t *data; + /** + * Length of account data. + */ + uintptr_t data_len; + /** + * Nonce as little-endian [u8; 16]. + */ + struct FfiU128 nonce; +} FfiAccount; + +typedef struct FfiVec_FfiAccount { + struct FfiAccount *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiAccount; + +typedef struct FfiVec_FfiAccount FfiAccountList; + +typedef struct FfiVec_u8 { + uint8_t *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_u8; + +typedef struct FfiVec_u8 FfiVecU8; + +typedef struct FfiEncryptedAccountData { + FfiVecU8 ciphertext; + FfiVecU8 epk; + uint8_t view_tag; +} FfiEncryptedAccountData; + +typedef struct FfiVec_FfiEncryptedAccountData { + struct FfiEncryptedAccountData *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiEncryptedAccountData; + +typedef struct FfiVec_FfiEncryptedAccountData FfiEncryptedAccountDataList; + +typedef struct FfiVec_FfiBytes32 { + struct FfiBytes32 *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiBytes32; + +typedef struct FfiVec_FfiBytes32 FfiVecBytes32; + +typedef struct FfiNullifierCommitmentSet { + struct FfiBytes32 nullifier; + struct FfiBytes32 commitment_set_digest; +} FfiNullifierCommitmentSet; + +typedef struct FfiVec_FfiNullifierCommitmentSet { + struct FfiNullifierCommitmentSet *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiNullifierCommitmentSet; + +typedef struct FfiVec_FfiNullifierCommitmentSet FfiNullifierCommitmentSetList; + +typedef struct FfiPrivacyPreservingMessage { + FfiAccountIdList public_account_ids; + FfiNonceList nonces; + FfiAccountList public_post_states; + FfiEncryptedAccountDataList encrypted_private_post_states; + FfiVecBytes32 new_commitments; + FfiNullifierCommitmentSetList new_nullifiers; + uint64_t block_validity_window[2]; + uint64_t timestamp_validity_window[2]; +} FfiPrivacyPreservingMessage; + +typedef FfiVecU8 FfiProof; + +typedef struct FfiPrivateTransactionBody { + FfiHashType hash; + struct FfiPrivacyPreservingMessage message; + FfiSignaturePubKeyList witness_set; + FfiProof proof; +} FfiPrivateTransactionBody; + +typedef FfiVecU8 FfiProgramDeploymentMessage; + +typedef struct FfiProgramDeploymentTransactionBody { + FfiHashType hash; + FfiProgramDeploymentMessage message; +} FfiProgramDeploymentTransactionBody; + +typedef struct FfiTransactionBody { + struct FfiPublicTransactionBody *public_body; + struct FfiPrivateTransactionBody *private_body; + struct FfiProgramDeploymentTransactionBody *program_deployment_body; +} FfiTransactionBody; + +typedef struct FfiTransaction { + struct FfiTransactionBody body; + enum FfiTransactionKind kind; +} FfiTransaction; + +typedef struct FfiVec_FfiTransaction { + struct FfiTransaction *entries; + uintptr_t len; + uintptr_t capacity; +} FfiVec_FfiTransaction; + +typedef struct FfiVec_FfiTransaction FfiBlockBody; + +typedef struct FfiBytes32 FfiMsgId; + +typedef struct FfiBlock { + struct FfiBlockHeader header; + FfiBlockBody body; + enum FfiBedrockStatus bedrock_status; + FfiMsgId bedrock_parent_id; +} FfiBlock; + +typedef struct FfiOption_FfiBlock { + struct FfiBlock *value; + bool is_some; +} FfiOption_FfiBlock; + +typedef struct FfiOption_FfiBlock FfiBlockOpt; + /** * Simple wrapper around a pointer to a value or an error. * * Pointer is not guaranteed. You should check the error field before * dereferencing the pointer. */ -typedef struct PointerResult_BlockOpt__OperationStatus { - BlockOpt *value; +typedef struct PointerResult_FfiBlockOpt__OperationStatus { + FfiBlockOpt *value; enum OperationStatus error; -} PointerResult_BlockOpt__OperationStatus; +} PointerResult_FfiBlockOpt__OperationStatus; /** * Creates and starts an indexer based on the provided @@ -133,8 +384,8 @@ struct PointerResult_u64__OperationStatus query_last_block(const struct IndexerS * - The `IndexerServiceFFI` instance was created by this library * - The pointer will not be used after this function returns */ -struct PointerResult_BlockOpt__OperationStatus query_block(const struct IndexerServiceFFI *indexer, - BlockId block_id); +struct PointerResult_FfiBlockOpt__OperationStatus query_block(const struct IndexerServiceFFI *indexer, + FfiBlockId block_id); bool is_ok(const enum OperationStatus *self); diff --git a/indexer_ffi/src/api/convert.rs b/indexer_ffi/src/api/convert.rs deleted file mode 100644 index f5636b89..00000000 --- a/indexer_ffi/src/api/convert.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::api::types::BlockOpt; - -impl From> for BlockOpt { - fn from(value: Option) -> Self { - match value { - None => BlockOpt { - block: std::ptr::null_mut(), - is_ok: false, - }, - Some(block_orig) => BlockOpt { - block: block_orig.into(), - is_ok: true, - }, - } - } -} diff --git a/indexer_ffi/src/api/lifecycle.rs b/indexer_ffi/src/api/lifecycle.rs index 087f7803..15c6e619 100644 --- a/indexer_ffi/src/api/lifecycle.rs +++ b/indexer_ffi/src/api/lifecycle.rs @@ -1,6 +1,6 @@ use std::{ffi::c_char, path::PathBuf}; -use sequencer_core::indexer_client::{IndexerClient, IndexerClientTrait}; +use sequencer_core::indexer_client::{IndexerClient, IndexerClientTrait as _}; use tokio::runtime::Runtime; use crate::{ diff --git a/indexer_ffi/src/api/mod.rs b/indexer_ffi/src/api/mod.rs index 4c80629b..ea2b91d7 100644 --- a/indexer_ffi/src/api/mod.rs +++ b/indexer_ffi/src/api/mod.rs @@ -1,7 +1,6 @@ pub use result::PointerResult; pub mod client; -pub mod convert; pub mod lifecycle; pub mod memory; pub mod query; diff --git a/indexer_ffi/src/api/query.rs b/indexer_ffi/src/api/query.rs index 510f1383..e840fed7 100644 --- a/indexer_ffi/src/api/query.rs +++ b/indexer_ffi/src/api/query.rs @@ -1,10 +1,10 @@ -use indexer_service_rpc::RpcClient; +use indexer_service_rpc::RpcClient as _; use crate::{ IndexerServiceFFI, api::{ PointerResult, - types::{Block, BlockId, BlockOpt}, + types::{FfiBlockId, block::FfiBlockOpt}, }, errors::OperationStatus, }; @@ -66,8 +66,8 @@ pub unsafe extern "C" fn query_last_block( #[unsafe(no_mangle)] pub unsafe extern "C" fn query_block( indexer: *const IndexerServiceFFI, - block_id: BlockId, -) -> PointerResult { + block_id: FfiBlockId, +) -> PointerResult { if indexer.is_null() { log::error!("Attempted to query a null indexer pointer. This is a bug. Aborting."); return PointerResult::from_error(OperationStatus::NullPointer); @@ -82,6 +82,12 @@ pub unsafe extern "C" fn query_block( .block_on(client.get_block_by_id(block_id)) .map_or_else( |_| PointerResult::from_error(OperationStatus::ClientError), - |block| PointerResult::from_value(block.into()), + |block_opt| { + let block_ffi = block_opt.map_or_else(FfiBlockOpt::from_none, |block| { + FfiBlockOpt::from_value(block.into()) + }); + + PointerResult::from_value(block_ffi) + }, ) } diff --git a/indexer_ffi/src/api/types/account.rs b/indexer_ffi/src/api/types/account.rs index e36230ae..568bfa1c 100644 --- a/indexer_ffi/src/api/types/account.rs +++ b/indexer_ffi/src/api/types/account.rs @@ -2,7 +2,7 @@ use std::ptr; -use crate::api::types::FfiVec; +use indexer_service_protocol::ProgramId; /// 32-byte array type for `AccountId`, keys, hashes, etc. #[repr(C)] @@ -31,6 +31,12 @@ pub struct FfiProgramId { pub data: [u32; 8], } +impl From for FfiProgramId { + fn from(value: ProgramId) -> Self { + Self { data: value.0 } + } +} + /// U128 - 16 bytes little endian. #[repr(C)] #[derive(Clone, Copy, Default)] @@ -55,12 +61,6 @@ pub struct FfiAccount { pub nonce: FfiU128, } -#[repr(C)] -pub struct FfiAccountList { - pub entries: *const FfiAccount, - pub len: usize, -} - impl Default for FfiAccount { fn default() -> Self { Self { @@ -101,32 +101,6 @@ pub struct FfiPublicAccountKey { pub public_key: FfiBytes32, } -/// Single entry in the account list. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct FfiAccountIdListEntry { - pub account_id: FfiBytes32, - pub is_public: bool, -} - -/// List of accounts returned by `wallet_ffi_list_accounts`. -#[repr(C)] -pub struct FfiAccountIdList { - pub entries: *mut FfiAccountIdListEntry, - pub count: usize, -} - -impl Default for FfiAccountIdList { - fn default() -> Self { - Self { - entries: std::ptr::null_mut(), - count: 0, - } - } -} - -pub type FfiVecBytes32 = FfiVec; - // Helper functions to convert between Rust and FFI types impl FfiBytes32 { diff --git a/indexer_ffi/src/api/types/block.rs b/indexer_ffi/src/api/types/block.rs index a31bd495..1ee8215f 100644 --- a/indexer_ffi/src/api/types/block.rs +++ b/indexer_ffi/src/api/types/block.rs @@ -1,6 +1,7 @@ +use indexer_service_protocol::{BedrockStatus, Block, BlockHeader}; + use crate::api::types::{ - FfiBlockId, FfiHashType, FfiMsgId, FfiSignature, FfiTimestamp, FfiVec, - transaction::FfiTransaction, + FfiBlockId, FfiHashType, FfiMsgId, FfiOption, FfiSignature, FfiTimestamp, vectors::FfiBlockBody, }; #[repr(C)] @@ -11,13 +12,24 @@ pub struct FfiBlock { pub bedrock_parent_id: FfiMsgId, } -#[repr(C)] -pub struct FfiBlockOpt { - pub block: *const FfiBlock, - pub is_some: bool, +impl From for FfiBlock { + fn from(value: Block) -> Self { + Self { + header: value.header.into(), + body: value + .body + .transactions + .into_iter() + .map(Into::into) + .collect::>() + .into(), + bedrock_status: value.bedrock_status.into(), + bedrock_parent_id: value.bedrock_parent_id.into(), + } + } } -pub type FfiBlockBody = FfiVec; +pub type FfiBlockOpt = FfiOption; #[repr(C)] pub struct FfiBlockHeader { @@ -28,9 +40,31 @@ pub struct FfiBlockHeader { pub signature: FfiSignature, } +impl From for FfiBlockHeader { + fn from(value: BlockHeader) -> Self { + Self { + block_id: value.block_id, + prev_block_hash: value.prev_block_hash.into(), + hash: value.hash.into(), + timestamp: value.timestamp, + signature: value.signature.into(), + } + } +} + #[repr(C)] pub enum FfiBedrockStatus { Pending = 0x0, Safe, Finalized, } + +impl From for FfiBedrockStatus { + fn from(value: BedrockStatus) -> Self { + match value { + BedrockStatus::Finalized => Self::Finalized, + BedrockStatus::Pending => Self::Pending, + BedrockStatus::Safe => Self::Safe, + } + } +} diff --git a/indexer_ffi/src/api/types/mod.rs b/indexer_ffi/src/api/types/mod.rs index 73336c05..d1b3e572 100644 --- a/indexer_ffi/src/api/types/mod.rs +++ b/indexer_ffi/src/api/types/mod.rs @@ -1,8 +1,11 @@ +use indexer_service_protocol::{AccountId, HashType, MantleMsgId, PublicKey, Signature}; + use crate::api::types::account::{FfiBytes32, FfiBytes64, FfiU128}; pub mod account; pub mod block; pub mod transaction; +pub mod vectors; pub type FfiHashType = FfiBytes32; pub type FfiMsgId = FfiBytes32; @@ -13,17 +16,73 @@ pub type FfiAccountId = FfiBytes32; pub type FfiNonce = FfiU128; pub type FfiPublicKey = FfiBytes32; -#[repr(C)] -pub struct FfiVec { - pub entries: *const T, - pub len: usize, +impl From for FfiHashType { + fn from(value: HashType) -> Self { + Self { data: value.0 } + } } -impl Default for FfiVec { - fn default() -> Self { +impl From for FfiMsgId { + fn from(value: MantleMsgId) -> Self { + Self { data: value.0 } + } +} + +impl From for FfiSignature { + fn from(value: Signature) -> Self { + Self { data: value.0 } + } +} + +impl From for FfiAccountId { + fn from(value: AccountId) -> Self { + Self { data: value.value } + } +} + +impl From for FfiPublicKey { + fn from(value: PublicKey) -> Self { + Self { data: value.0 } + } +} + +#[repr(C)] +pub struct FfiVec { + pub entries: *mut T, + pub len: usize, + pub capacity: usize, +} + +impl From> for FfiVec { + fn from(value: Vec) -> Self { + let (entries, len, capacity) = value.into_raw_parts(); Self { - entries: std::ptr::null(), - len: 0, + entries, + len, + capacity, + } + } +} + +#[repr(C)] +pub struct FfiOption { + pub value: *mut T, + pub is_some: bool, +} + +impl FfiOption { + pub fn from_value(val: T) -> Self { + Self { + value: Box::into_raw(Box::new(val)), + is_some: true, + } + } + + #[must_use] + pub const fn from_none() -> Self { + Self { + value: std::ptr::null_mut(), + is_some: false, } } } diff --git a/indexer_ffi/src/api/types/transaction.rs b/indexer_ffi/src/api/types/transaction.rs index 4f92d492..86e28133 100644 --- a/indexer_ffi/src/api/types/transaction.rs +++ b/indexer_ffi/src/api/types/transaction.rs @@ -1,6 +1,17 @@ +use indexer_service_protocol::{ + CommitmentSetDigest, EncryptedAccountData, Nullifier, PrivacyPreservingMessage, + PrivacyPreservingTransaction, ProgramDeploymentTransaction, PublicKey, PublicMessage, + PublicTransaction, Signature, Transaction, ValidityWindow, +}; + use crate::api::types::{ - FfiHashType, FfiNonce, FfiPublicKey, FfiSignature, FfiVec, - account::{FfiAccountIdList, FfiAccountList, FfiBytes32, FfiProgramId, FfiVecBytes32}, + FfiHashType, FfiPublicKey, FfiSignature, + account::{FfiBytes32, FfiProgramId}, + vectors::{ + FfiAccountIdList, FfiAccountList, FfiEncryptedAccountDataList, FfiInstructionDataList, + FfiNonceList, FfiNullifierCommitmentSetList, FfiProgramDeploymentMessage, FfiProof, + FfiSignaturePubKeyList, FfiVecBytes32, FfiVecU8, + }, }; #[repr(C)] @@ -10,9 +21,21 @@ pub struct FfiPublicTransactionBody { pub witness_set: FfiSignaturePubKeyList, } -pub type FfiNonceList = FfiVec; - -pub type FfiInstructionDataList = FfiVec; +impl From for FfiPublicTransactionBody { + fn from(value: PublicTransaction) -> Self { + Self { + hash: value.hash.into(), + message: value.message.into(), + witness_set: value + .witness_set + .signatures_and_public_keys + .into_iter() + .map(Into::into) + .collect::>() + .into(), + } + } +} #[repr(C)] pub struct FfiPublicMessage { @@ -22,12 +45,55 @@ pub struct FfiPublicMessage { pub instruction_data: FfiInstructionDataList, } +impl From for FfiPublicMessage { + fn from(value: PublicMessage) -> Self { + Self { + program_id: value.program_id.into(), + account_ids: value + .account_ids + .into_iter() + .map(Into::into) + .collect::>() + .into(), + nonces: value + .nonces + .into_iter() + .map(Into::into) + .collect::>() + .into(), + instruction_data: value.instruction_data.into(), + } + } +} + #[repr(C)] pub struct FfiPrivateTransactionBody { pub hash: FfiHashType, pub message: FfiPrivacyPreservingMessage, pub witness_set: FfiSignaturePubKeyList, - pub proof: FfiProofOpt, + pub proof: FfiProof, +} + +impl From for FfiPrivateTransactionBody { + fn from(value: PrivacyPreservingTransaction) -> Self { + Self { + hash: value.hash.into(), + message: value.message.into(), + witness_set: value + .witness_set + .signatures_and_public_keys + .into_iter() + .map(Into::into) + .collect::>() + .into(), + proof: value + .witness_set + .proof + .expect("Private execution: proof must be present") + .0 + .into(), + } + } } #[repr(C)] @@ -35,41 +101,106 @@ pub struct FfiPrivacyPreservingMessage { pub public_account_ids: FfiAccountIdList, pub nonces: FfiNonceList, pub public_post_states: FfiAccountList, - pub encrypted_private_post_states: FfiVec, + pub encrypted_private_post_states: FfiEncryptedAccountDataList, pub new_commitments: FfiVecBytes32, - pub new_nullifiers: FfiVec, + pub new_nullifiers: FfiNullifierCommitmentSetList, pub block_validity_window: [u64; 2], pub timestamp_validity_window: [u64; 2], } +impl From for FfiPrivacyPreservingMessage { + fn from(value: PrivacyPreservingMessage) -> Self { + Self { + public_account_ids: value + .public_account_ids + .into_iter() + .map(Into::into) + .collect::>() + .into(), + nonces: value + .nonces + .into_iter() + .map(Into::into) + .collect::>() + .into(), + public_post_states: value + .public_post_states + .into_iter() + .map(|acc_ind| -> nssa::Account { + acc_ind.try_into().expect("Source is in blocks, must fit") + }) + .map(Into::into) + .collect::>() + .into(), + encrypted_private_post_states: value + .encrypted_private_post_states + .into_iter() + .map(Into::into) + .collect::>() + .into(), + new_commitments: value + .new_commitments + .into_iter() + .map(|comm| FfiBytes32 { data: comm.0 }) + .collect::>() + .into(), + new_nullifiers: value + .new_nullifiers + .into_iter() + .map(Into::into) + .collect::>() + .into(), + block_validity_window: cast_validity_window(value.block_validity_window), + timestamp_validity_window: cast_validity_window(value.timestamp_validity_window), + } + } +} + #[repr(C)] -pub struct NullifierCommitmentSet { +pub struct FfiNullifierCommitmentSet { pub nullifier: FfiBytes32, pub commitment_set_digest: FfiBytes32, } +impl From<(Nullifier, CommitmentSetDigest)> for FfiNullifierCommitmentSet { + fn from(value: (Nullifier, CommitmentSetDigest)) -> Self { + Self { + nullifier: FfiBytes32 { data: value.0.0 }, + commitment_set_digest: FfiBytes32 { data: value.1.0 }, + } + } +} + #[repr(C)] pub struct FfiEncryptedAccountData { - pub ciphertext: FfiVec, - pub epk: FfiVec, + pub ciphertext: FfiVecU8, + pub epk: FfiVecU8, pub view_tag: u8, } +impl From for FfiEncryptedAccountData { + fn from(value: EncryptedAccountData) -> Self { + Self { + ciphertext: value.ciphertext.0.into(), + epk: value.epk.0.into(), + view_tag: value.view_tag, + } + } +} + #[repr(C)] pub struct FfiSignaturePubKeyEntry { pub signature: FfiSignature, pub public_key: FfiPublicKey, } -pub struct FfiSignaturePubKeyList { - pub entries: *const FfiSignaturePubKeyEntry, - pub len: usize, -} - -#[repr(C)] -pub struct FfiProofOpt { - pub proof: FfiVec, - pub is_some: bool, +impl From<(Signature, PublicKey)> for FfiSignaturePubKeyEntry { + fn from(value: (Signature, PublicKey)) -> Self { + Self { + signature: value.0.into(), + public_key: value.1.into(), + } + } } #[repr(C)] @@ -78,13 +209,20 @@ pub struct FfiProgramDeploymentTransactionBody { pub message: FfiProgramDeploymentMessage, } -pub type FfiProgramDeploymentMessage = FfiVec; +impl From for FfiProgramDeploymentTransactionBody { + fn from(value: ProgramDeploymentTransaction) -> Self { + Self { + hash: value.hash.into(), + message: value.message.bytecode.into(), + } + } +} #[repr(C)] pub struct FfiTransactionBody { - pub public_body: *const FfiPublicTransactionBody, - pub private_body: *const FfiPrivateTransactionBody, - pub program_deployment_body: *const FfiProgramDeploymentTransactionBody, + pub public_body: *mut FfiPublicTransactionBody, + pub private_body: *mut FfiPrivateTransactionBody, + pub program_deployment_body: *mut FfiProgramDeploymentTransactionBody, } #[repr(C)] @@ -93,9 +231,47 @@ pub struct FfiTransaction { pub kind: FfiTransactionKind, } +impl From for FfiTransaction { + fn from(value: Transaction) -> Self { + match value { + Transaction::Public(pub_tx) => Self { + body: FfiTransactionBody { + public_body: Box::into_raw(Box::new(pub_tx.into())), + private_body: std::ptr::null_mut(), + program_deployment_body: std::ptr::null_mut(), + }, + kind: FfiTransactionKind::Public, + }, + Transaction::PrivacyPreserving(priv_tx) => Self { + body: FfiTransactionBody { + public_body: std::ptr::null_mut(), + private_body: Box::into_raw(Box::new(priv_tx.into())), + program_deployment_body: std::ptr::null_mut(), + }, + kind: FfiTransactionKind::Public, + }, + Transaction::ProgramDeployment(pr_dep_tx) => Self { + body: FfiTransactionBody { + public_body: std::ptr::null_mut(), + private_body: std::ptr::null_mut(), + program_deployment_body: Box::into_raw(Box::new(pr_dep_tx.into())), + }, + kind: FfiTransactionKind::Public, + }, + } + } +} + #[repr(C)] pub enum FfiTransactionKind { Public = 0x0, Private, ProgramDeploy, } + +fn cast_validity_window(window: ValidityWindow) -> [u64; 2] { + [ + window.0.0.unwrap_or_default(), + window.0.1.unwrap_or(u64::MAX), + ] +} diff --git a/indexer_ffi/src/api/types/vectors.rs b/indexer_ffi/src/api/types/vectors.rs new file mode 100644 index 00000000..7c8c2073 --- /dev/null +++ b/indexer_ffi/src/api/types/vectors.rs @@ -0,0 +1,31 @@ +use crate::api::types::{ + FfiAccountId, FfiNonce, FfiVec, + account::{FfiAccount, FfiBytes32}, + transaction::{ + FfiEncryptedAccountData, FfiNullifierCommitmentSet, FfiSignaturePubKeyEntry, FfiTransaction, + }, +}; + +pub type FfiVecU8 = FfiVec; + +pub type FfiAccountList = FfiVec; + +pub type FfiAccountIdList = FfiVec; + +pub type FfiVecBytes32 = FfiVec; + +pub type FfiBlockBody = FfiVec; + +pub type FfiNonceList = FfiVec; + +pub type FfiInstructionDataList = FfiVec; + +pub type FfiSignaturePubKeyList = FfiVec; + +pub type FfiProof = FfiVecU8; + +pub type FfiProgramDeploymentMessage = FfiVecU8; + +pub type FfiEncryptedAccountDataList = FfiVec; + +pub type FfiNullifierCommitmentSetList = FfiVec; diff --git a/integration_tests/src/test_context_ffi.rs b/integration_tests/src/test_context_ffi.rs index 1bda9e2c..cdf7db9a 100644 --- a/integration_tests/src/test_context_ffi.rs +++ b/integration_tests/src/test_context_ffi.rs @@ -271,7 +271,7 @@ impl BlockingTestContextFFI { #[must_use] pub const fn indexer_ffi(&self) -> *const IndexerServiceFFI { - &(self.indexer_ffi) + &raw const (self.indexer_ffi) } } diff --git a/integration_tests/tests/indexer_ffi.rs b/integration_tests/tests/indexer_ffi.rs index b75f1b2b..d0c643f7 100644 --- a/integration_tests/tests/indexer_ffi.rs +++ b/integration_tests/tests/indexer_ffi.rs @@ -1,6 +1,7 @@ #![expect( clippy::shadow_unrelated, clippy::tests_outside_test_module, + clippy::undocumented_unsafe_blocks, reason = "We don't care about these in tests" )]