Skip to content

chore(key-wallet-ffi): drop key-wallet ffi functions that are not being used in the swift-sdk#528

Draft
ZocoLini wants to merge 1 commit intov0.42-devfrom
chore/drop-unused-keywallet-ffi
Draft

chore(key-wallet-ffi): drop key-wallet ffi functions that are not being used in the swift-sdk#528
ZocoLini wants to merge 1 commit intov0.42-devfrom
chore/drop-unused-keywallet-ffi

Conversation

@ZocoLini
Copy link
Collaborator

@ZocoLini ZocoLini commented Mar 12, 2026

I wanted to see what we are currently exposing through FFI versus what we are actually using. This is not meant to be merged (yet), but rather to serve as a guide for what is not yet implemented or may be unnecessary.

  • Some methods like collection_account_do_something are not being used, but at the same time there are some managed_collection_account_do_something methods that I suspect contain the same logic. I didn’t verify that yet, but I will eventually.
  • Some methods are being used, but I suspect their Swift SDK wrappers aren’t.
  • I didn’t verify the usage of FFI structures.
    -I didn’t update the tests; I will remove those that test removed methods.

Summary by CodeRabbit

  • Breaking Changes

    • Removed BIP38 encryption support.
    • Simplified FFI API surface: removed numerous account, key derivation, and transaction utility functions.
    • Restructured account access from individual getters to collection-based queries with summary data.
    • Deprecated mnemonic generation without language parameter.
  • Refactor

    • Consolidated wallet operations toward wallet-centric and collection-oriented abstractions.
    • Streamlined public API with reduced function count and improved memory management patterns.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Refactors key-wallet-ffi's public C API to a wallet-centric, collection-driven model: removes many per-account and low-level key/transaction FFI functions, introduces account-collection/summary, address-pool, managed-wallet APIs, and removes bip38 feature and module export. Adds FFINetwork enum and various managed-wallet helpers.

Changes

Cohort / File(s) Summary
Build / Feature
key-wallet-ffi/Cargo.toml, key-wallet-ffi/src/lib.rs
Removed bip38 from default features and deleted bip38 public module export; trimmed wallet_manager re-exports (removed describe/free helpers).
Public Header
key-wallet-ffi/include/key_wallet_ffi.h
Reworked public API: added FFINetwork enum, wallet-centric APIs (wallet_get_account_count, wallet_get_account_collection, wallet_manager_*), account-collection/summary and address-pool declarations; many per-account getters removed.
Account Surface
key-wallet-ffi/src/account.rs, key-wallet-ffi/src/account_collection.rs
Removed numerous per-account/getter FFI functions for Account/BLS/EdDSA; consolidated to collection+summary pattern and lifecycle (free) functions.
Derivation / Keys
key-wallet-ffi/src/account_derivation.rs, key-wallet-ffi/src/derivation.rs, key-wallet-ffi/src/keys.rs
Removed large set of seed/mnemonic and per-account derivation entry points and many key conversion/free helpers; retained a small set of wallet-centric derivation helpers (e.g., xpriv/xpub paths, WIF/hex helpers).
BIP38
key-wallet-ffi/src/bip38.rs
Removed entire BIP38 module and its encrypt/decrypt FFI functions.
Managed Wallet / Accounts
key-wallet-ffi/src/managed_account.rs, key-wallet-ffi/src/managed_account_collection.rs, key-wallet-ffi/src/managed_wallet.rs
Removed DashPay- and Platform-payment-specific FFI accessors and string summaries; added structured managed-account collection summary APIs and new managed-wallet account/getters; removed some managed_wallet free/synced helpers.
Transactions / UTXO
key-wallet-ffi/src/transaction.rs, key-wallet-ffi/src/utxo.rs
Removed transaction construction/signing/serialization/deserialization and low-level script/address utilities; retained wallet-driven wallet_build_and_sign_transaction, wallet_check_transaction, and transaction_bytes_free; removed deprecated wallet_get_utxos wrapper.
Utilities & Types
key-wallet-ffi/src/types.rs, key-wallet-ffi/src/utils.rs, key-wallet-ffi/src/wallet.rs, key-wallet-ffi/src/wallet_manager.rs, key-wallet-ffi/src/mnemonic.rs
Removed ffi_network_get_name and some AccountType helpers, removed c-string helper, removed several wallet xpub/add-account APIs and wallet_manager describe/free string/address helpers; promoted mnemonic_generate_with_language and removed default mnemonic_generate.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client as Client
  rect rgba(200,200,255,0.5)
    participant WM as WalletManager
  end
  rect rgba(200,255,200,0.5)
    participant W as Wallet
    participant MW as ManagedWallet
    participant AP as AddressPool
  end

  Client->>WM: wallet_manager_get_wallet_ids()
  Client->>WM: wallet_manager_get_wallet(wallet_id)
  Client->>WM: wallet_manager_get_managed_wallet_info(wallet_id)
  WM->>W: wallet_get_account_collection(wallet)
  W->>MW: wallet_get_account_collection -> FFIAccountCollection
  Client->>MW: managed_wallet_get_address_pool_info(account_index, pool_type)
  MW->>AP: managed_core_account_get_address_pool(account)
  AP-->>Client: address_pool_get_addresses_in_range(...)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through headers, trimmed the weeds away,
From many getters to collections we play,
Bip38 tucked into a burrow deep,
Wallets and pools now dance in tidy heaps,
A carrot-toast to APIs — clean and spry!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: removing unused FFI functions from the key-wallet-ffi crate that are not being used by the swift-sdk.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/drop-unused-keywallet-ffi
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Mar 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.51%. Comparing base (33cefc9) to head (ee4fffe).
⚠️ Report is 2 commits behind head on v0.42-dev.

Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #528      +/-   ##
=============================================
+ Coverage      66.90%   67.51%   +0.60%     
=============================================
  Files            313      313              
  Lines          64757    62269    -2488     
=============================================
- Hits           43325    42038    -1287     
+ Misses         21432    20231    -1201     
Flag Coverage Δ *Carryforward flag
core 75.02% <ø> (+0.09%) ⬆️
dash-network 74.91% <ø> (ø) Carriedforward from 33cefc9
dash-network-ffi 40.46% <ø> (+5.69%) ⬆️ Carriedforward from 33cefc9
dash-spv 68.26% <ø> (ø) Carriedforward from 33cefc9
dash-spv-ffi 40.46% <ø> (+5.69%) ⬆️ Carriedforward from 33cefc9
dashcore 74.91% <ø> (ø) Carriedforward from 33cefc9
dashcore-private 74.91% <ø> (ø) Carriedforward from 33cefc9
dashcore-rpc 19.92% <ø> (ø) Carriedforward from 33cefc9
dashcore-rpc-json 19.92% <ø> (ø) Carriedforward from 33cefc9
dashcore_hashes 74.91% <ø> (ø) Carriedforward from 33cefc9
ffi ?
key-wallet 65.65% <ø> (ø) Carriedforward from 33cefc9
key-wallet-ffi 40.46% <ø> (+5.69%) ⬆️ Carriedforward from 33cefc9
key-wallet-manager 65.65% <ø> (ø) Carriedforward from 33cefc9
rpc 19.92% <ø> (ø)
spv 81.17% <ø> (+0.06%) ⬆️
wallet 65.68% <ø> (ø)

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
key-wallet-ffi/src/account.rs 38.23% <ø> (+11.41%) ⬆️
key-wallet-ffi/src/account_collection.rs 87.30% <ø> (+13.31%) ⬆️
key-wallet-ffi/src/account_derivation.rs 0.00% <ø> (ø)
key-wallet-ffi/src/derivation.rs 22.00% <ø> (-8.72%) ⬇️
key-wallet-ffi/src/keys.rs 0.00% <ø> (-26.57%) ⬇️
key-wallet-ffi/src/lib.rs 50.00% <ø> (ø)
key-wallet-ffi/src/managed_account.rs 60.50% <ø> (+6.89%) ⬆️
key-wallet-ffi/src/managed_account_collection.rs 23.12% <ø> (-18.15%) ⬇️
key-wallet-ffi/src/managed_wallet.rs 47.48% <ø> (-15.95%) ⬇️
key-wallet-ffi/src/mnemonic.rs 53.88% <ø> (-5.38%) ⬇️
... and 6 more

... and 12 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ZocoLini ZocoLini force-pushed the chore/drop-unused-keywallet-ffi branch from 8ddba5f to ee4fffe Compare March 12, 2026 19:40
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (8)
key-wallet-ffi/src/wallet_manager.rs (1)

57-80: ⚠️ Potential issue | 🔴 Critical

Restore a public destructor for wallet_manager_create.

This function still transfers ownership of a heap-allocated FFIWalletManager to FFI callers, but this module no longer exposes any matching wallet_manager_free. key-wallet-ffi/src/wallet_manager_tests.rs:36-38 still calls that symbol, so the test target now fails to compile, and external callers have no supported way to release the manager/runtime.

Suggested fix
 #[no_mangle]
 pub extern "C" fn wallet_manager_create(
     network: FFINetwork,
     error: *mut FFIError,
 ) -> *mut FFIWalletManager {
@@
     Box::into_raw(Box::new(FFIWalletManager {
         network,
         manager: Arc::new(RwLock::new(manager)),
         runtime,
     }))
 }
+
+/// Free wallet manager
+///
+/// # Safety
+/// - `manager` must be a valid pointer returned by `wallet_manager_create` or null
+/// - The pointer must not be used after calling this function
+#[no_mangle]
+pub unsafe extern "C" fn wallet_manager_free(manager: *mut FFIWalletManager) {
+    if !manager.is_null() {
+        let _ = Box::from_raw(manager);
+    }
+}
As per coding guidelines `**/*-ffi/**/*.rs`: Handle memory safety carefully at FFI boundaries.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/wallet_manager.rs` around lines 57 - 80,
wallet_manager_create transfers ownership of an FFIWalletManager to callers but
no destructor is exposed; add a public extern "C" destructor named
wallet_manager_free that reverses that transfer, is safe for null, and is usable
by tests and external callers. Implement wallet_manager_free(ptr: *mut
FFIWalletManager, error: *mut FFIError) as an extern "C" fn that returns void,
checks for null, uses Box::from_raw to reclaim the allocation, properly shuts
down or drops the contained runtime and manager (drop the
Arc<RwLock<WalletManager>> and cleanly stop the tokio::runtime::Runtime), and
set FFIError success/failure via FFIError::set_success/set_error; ensure symbol
name matches wallet_manager_free expected by tests and FFI consumers.
key-wallet-ffi/src/managed_wallet.rs (1)

592-606: ⚠️ Potential issue | 🔴 Critical

Keep a managed_wallet_free alias, or rename all remaining call sites in this PR.

The module now only exports managed_wallet_info_free, but the in-file tests below still call managed_wallet_free (for example at Lines 624-628 and Lines 792-796). That makes the test target fail to compile and drops a previously public deallocator name without a compatibility shim.

Suggested fix
 #[no_mangle]
 pub unsafe extern "C" fn managed_wallet_info_free(wallet_info: *mut FFIManagedWalletInfo) {
     if !wallet_info.is_null() {
         let wrapper = Box::from_raw(wallet_info);
         if !wrapper.inner.is_null() {
             let _ = Box::from_raw(wrapper.inner as *mut ManagedWalletInfo);
         }
     }
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn managed_wallet_free(managed_wallet: *mut FFIManagedWalletInfo) {
+    managed_wallet_info_free(managed_wallet);
+}
As per coding guidelines `**/*-ffi/**/*.rs`: Handle memory safety carefully at FFI boundaries.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/managed_wallet.rs` around lines 592 - 606, Tests and other
call sites still reference the old deallocator name managed_wallet_free while
the module only exposes managed_wallet_info_free; restore compatibility by
adding a no_mangle public alias function named managed_wallet_free that simply
forwards to managed_wallet_info_free (e.g., define #[no_mangle] pub unsafe
extern "C" fn managed_wallet_free(wallet_info: *mut FFIManagedWalletInfo) {
managed_wallet_info_free(wallet_info); }), or alternatively rename all remaining
call sites to use managed_wallet_info_free consistently; reference the functions
managed_wallet_info_free and managed_wallet_free when locating where to add the
shim or update usages.
key-wallet-ffi/src/transaction.rs (2)

337-345: ⚠️ Potential issue | 🔴 Critical

Fix critical memory safety violation at FFI boundary in transaction bytes handling.

wallet_build_and_sign_transaction allocates a boxed slice (Box<[u8]>), then casts it to *mut u8, discarding the slice length metadata. When transaction_bytes_free attempts to reconstruct the pointer with Box::from_raw(tx_bytes), it treats it as a single u8 rather than a slice, causing undefined behavior during deallocation. This violates FFI memory safety requirements.

Use libc::malloc and libc::free to manage the transaction bytes—consistent with C allocation semantics at FFI boundaries:

Suggested fix
-            let boxed = serialized.into_boxed_slice();
-            let tx_bytes = Box::into_raw(boxed) as *mut u8;
+            let tx_bytes = libc::malloc(size) as *mut u8;
+            if tx_bytes.is_null() {
+                FFIError::set_error(
+                    error,
+                    FFIErrorCode::AllocationFailed,
+                    "Failed to allocate transaction bytes".to_string(),
+                );
+                return false;
+            }
+            ptr::copy_nonoverlapping(serialized.as_ptr(), tx_bytes, size);
 
             *tx_bytes_out = tx_bytes;
             *tx_len_out = size;
@@
 #[no_mangle]
 pub unsafe extern "C" fn transaction_bytes_free(tx_bytes: *mut u8) {
     if !tx_bytes.is_null() {
-        unsafe {
-            let _ = Box::from_raw(tx_bytes);
-        }
+        libc::free(tx_bytes.cast());
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/transaction.rs` around lines 337 - 345, The current
wallet_build_and_sign_transaction creates a Box<[u8]> and exposes its pointer as
*mut u8 which loses the slice metadata and causes undefined behavior when
transaction_bytes_free reconstructs with Box::from_raw; instead, allocate raw
memory with libc::malloc of size serialized.len(), memcpy or
ptr::copy_nonoverlapping the serialized bytes into that malloc'd buffer, set
*tx_bytes_out to the returned pointer and *tx_len_out to the length, and update
transaction_bytes_free to call libc::free on the pointer (ensuring it accepts
the same pointer type), removing any use of Box::into_raw/Box::from_raw for the
byte buffer to maintain correct FFI allocation semantics for
wallet_build_and_sign_transaction and transaction_bytes_free.

481-483: ⚠️ Potential issue | 🔴 Critical

wallet_check_transaction can panic and has memory safety issues in FFI boundaries.

This entrypoint calls tokio::runtime::Handle::current() which panics when the caller is not already inside a Tokio runtime. For a C/Swift FFI API that crashes instead of returning an FFIError. Additionally, the transaction bytes allocation/deallocation has undefined behavior: serialized.into_boxed_slice() creates a Box<[u8]>, but casting it to *mut u8 loses the slice metadata. The deallocation then tries to reconstruct with Box::from_raw() treating it as Box<u8>, causing a type mismatch across the FFI boundary.

Solutions: (1) Store an Arc<tokio::runtime::Runtime> as a field (see FFIWalletManager for the correct pattern) and call runtime.block_on() instead of Handle::current().block_on(). (2) For transaction bytes, either use a stable layout like a struct wrapping *mut u8 with explicit length, or preserve the slice metadata through the FFI boundary without casting away type information.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/transaction.rs` around lines 481 - 483, The
wallet_check_transaction FFI entry currently calls
tokio::runtime::Handle::current() (and uses serialized.into_boxed_slice() then
casts away slice metadata), which can panic outside a Tokio runtime and cause UB
when deallocating bytes; fix by switching to the same runtime pattern used in
FFIWalletManager: store an Arc<tokio::runtime::Runtime> on the wallet manager
and call runtime.block_on(managed_info.check_core_transaction(...)) instead of
Handle::current(), and change the transaction byte handling to preserve
length/metadata across the FFI boundary (e.g. pass a struct with *mut u8 plus
length or keep a Box<[u8]> and transfer it without casting to *mut u8 so you can
reconstruct with Box<[u8]>::from_raw when freeing) to avoid casting Box<[u8]> to
Box<u8> and the resulting type/size mismatch.
key-wallet-ffi/src/account_collection.rs (1)

306-579: ⚠️ Potential issue | 🔴 Critical

The test module still targets APIs removed by this refactor.

These cases still reference account_collection_count, account_collection_get_bip44_indices, account_collection_get_bip44_account, free_u32_array, account_collection_summary, account_collection_has_provider_operator_keys, and the provider-platform helpers, none of which exist in this module anymore. Because the tests import super::*, cargo test will fail to compile until they're rewritten to use account_collection_summary_data / the remaining entry points or deleted.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/account_collection.rs` around lines 306 - 579, Tests
reference removed FFI functions (account_collection_count,
account_collection_get_bip44_indices, account_collection_get_bip44_account,
free_u32_array, account_collection_summary,
account_collection_has_provider_operator_keys, provider-platform helpers);
update or remove them so tests compile: replace uses of
account_collection_summary/account_collection_summary_null_safety with
account_collection_summary_data and assert on the returned struct/string fields,
map calls that queried BIP44/BIP32/coinjoin/topup indices to the corresponding
fields on account_collection_summary_data, replace provider operator/platform
account helpers with the new summary data flags or account-specific getters if
available, and remove/free any arrays via the new API's ownership conventions
(do not call free_u32_array). Alternatively delete the obsolete tests that no
longer apply. Ensure you reference account_collection_summary_data,
wallet_get_account_collection, and any new summary field names when making
changes.
key-wallet-ffi/src/managed_account.rs (1)

1035-1094: ⚠️ Potential issue | 🔴 Critical

Update the test module to stop calling removed helpers.

managed_wallet_get_account_count and managed_core_account_get_parent_wallet_id are no longer defined in this module, but the test module still calls them through use super::*. That makes the #[cfg(test)] target fail to compile until these cases are rewritten against the remaining account/collection APIs or removed.

Also applies to: 1187-1189

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/managed_account.rs` around lines 1035 - 1094, The test
calls removed helpers managed_wallet_get_account_count and
managed_core_account_get_parent_wallet_id (via use super::*); update the test(s)
(e.g., test_managed_wallet_get_account_count) to stop calling these removed
functions — either remove those assertions/calls or rewrite the checks to use
the remaining public account/collection APIs (replace the managed_* calls with
the appropriate wallet-manager/account enumeration functions present in the
module), and ensure the test imports no longer rely on the deleted helpers.
key-wallet-ffi/include/key_wallet_ffi.h (1)

316-377: ⚠️ Potential issue | 🔴 Critical

Do not expose feature-dependent struct layouts through these summary APIs.

These declarations make FFIAccountCollectionSummary and FFIManagedCoreAccountCollectionSummary part of the public C ABI, but the Rust #[repr(C)] definitions in key-wallet-ffi/src/account_collection.rs and key-wallet-ffi/src/managed_account_collection.rs compile has_provider_operator_keys / has_provider_platform_keys in and out behind #[cfg]. The header always includes both fields, so builds without bls or eddsa produce a different layout than the one C/Swift was compiled against. FFIManagedCoreAccountCollectionSummary is especially unsafe because platform_payment_keys sits after those optional booleans. Please make the Rust structs feature-independent and default those flags to false, or generate feature-specific headers. As per coding guidelines, **/*-ffi/**/*.rs: Handle memory safety carefully at FFI boundaries.

Also applies to: 581-650, 915-940, 1975-2001

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/include/key_wallet_ffi.h` around lines 316 - 377, The public C
ABI structs (e.g., FFIAccountCollectionSummary and
FFIManagedCoreAccountCollectionSummary) expose feature-gated booleans
(has_provider_operator_keys, has_provider_platform_keys) which causes layout
mismatch; fix by making the Rust #[repr(C)] structs unconditionally include
those boolean fields (and any other feature-gated fields) and default them to
false in all build configurations so the layout matches the generated header,
and update the code that initializes/returns these structs to set those flags to
false when the feature is disabled (ensure platform_payment_keys remains at the
same offset). Alternatively, if you prefer feature-specific ABIs, make the
header generation conditional so the C header matches the exact Rust cfg layout
for each build. Ensure changes touch the Rust struct definitions used for FFI
and the header generation so the C header and Rust repr(C) layout are always
consistent.
key-wallet-ffi/src/wallet.rs (1)

400-445: ⚠️ Potential issue | 🟡 Minor

Replace the dead-end guidance in these error paths.

These notes/messages still tell callers to use wallet_add_platform_payment_account(), wallet_add_dashpay_receiving_account(), and wallet_add_dashpay_external_account_with_xpub_bytes(), but those entry points were removed in this PR. Please point callers to the actual supported replacement or return a neutral “unsupported through this FFI surface” error instead.

Also applies to: 494-547

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/wallet.rs` around lines 400 - 445, The error messages in
wallet_add_account that direct callers to removed functions
(wallet_add_platform_payment_account, wallet_add_dashpay_receiving_account,
wallet_add_dashpay_external_account_with_xpub_bytes) must be replaced: update
the match arms for FFIAccountType::PlatformPayment, ::DashpayReceivingFunds and
::DashpayExternalAccount to return a neutral unsupported error (e.g.
FFIAccountResult::error with FFIErrorCode::UnsupportedOperation or InvalidInput
and a message like "Account type <X> is not supported through this FFI surface")
or, if there is a real replacement API, point to that new API instead; apply the
same change to the repeated/error paths later in the file (the other matching
blocks around the 494-547 region) so callers are not pointed at removed entry
points.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@key-wallet-ffi/include/key_wallet_ffi.h`:
- Around line 316-377: The public C ABI structs (e.g.,
FFIAccountCollectionSummary and FFIManagedCoreAccountCollectionSummary) expose
feature-gated booleans (has_provider_operator_keys, has_provider_platform_keys)
which causes layout mismatch; fix by making the Rust #[repr(C)] structs
unconditionally include those boolean fields (and any other feature-gated
fields) and default them to false in all build configurations so the layout
matches the generated header, and update the code that initializes/returns these
structs to set those flags to false when the feature is disabled (ensure
platform_payment_keys remains at the same offset). Alternatively, if you prefer
feature-specific ABIs, make the header generation conditional so the C header
matches the exact Rust cfg layout for each build. Ensure changes touch the Rust
struct definitions used for FFI and the header generation so the C header and
Rust repr(C) layout are always consistent.

In `@key-wallet-ffi/src/account_collection.rs`:
- Around line 306-579: Tests reference removed FFI functions
(account_collection_count, account_collection_get_bip44_indices,
account_collection_get_bip44_account, free_u32_array,
account_collection_summary, account_collection_has_provider_operator_keys,
provider-platform helpers); update or remove them so tests compile: replace uses
of account_collection_summary/account_collection_summary_null_safety with
account_collection_summary_data and assert on the returned struct/string fields,
map calls that queried BIP44/BIP32/coinjoin/topup indices to the corresponding
fields on account_collection_summary_data, replace provider operator/platform
account helpers with the new summary data flags or account-specific getters if
available, and remove/free any arrays via the new API's ownership conventions
(do not call free_u32_array). Alternatively delete the obsolete tests that no
longer apply. Ensure you reference account_collection_summary_data,
wallet_get_account_collection, and any new summary field names when making
changes.

In `@key-wallet-ffi/src/managed_account.rs`:
- Around line 1035-1094: The test calls removed helpers
managed_wallet_get_account_count and managed_core_account_get_parent_wallet_id
(via use super::*); update the test(s) (e.g.,
test_managed_wallet_get_account_count) to stop calling these removed functions —
either remove those assertions/calls or rewrite the checks to use the remaining
public account/collection APIs (replace the managed_* calls with the appropriate
wallet-manager/account enumeration functions present in the module), and ensure
the test imports no longer rely on the deleted helpers.

In `@key-wallet-ffi/src/managed_wallet.rs`:
- Around line 592-606: Tests and other call sites still reference the old
deallocator name managed_wallet_free while the module only exposes
managed_wallet_info_free; restore compatibility by adding a no_mangle public
alias function named managed_wallet_free that simply forwards to
managed_wallet_info_free (e.g., define #[no_mangle] pub unsafe extern "C" fn
managed_wallet_free(wallet_info: *mut FFIManagedWalletInfo) {
managed_wallet_info_free(wallet_info); }), or alternatively rename all remaining
call sites to use managed_wallet_info_free consistently; reference the functions
managed_wallet_info_free and managed_wallet_free when locating where to add the
shim or update usages.

In `@key-wallet-ffi/src/transaction.rs`:
- Around line 337-345: The current wallet_build_and_sign_transaction creates a
Box<[u8]> and exposes its pointer as *mut u8 which loses the slice metadata and
causes undefined behavior when transaction_bytes_free reconstructs with
Box::from_raw; instead, allocate raw memory with libc::malloc of size
serialized.len(), memcpy or ptr::copy_nonoverlapping the serialized bytes into
that malloc'd buffer, set *tx_bytes_out to the returned pointer and *tx_len_out
to the length, and update transaction_bytes_free to call libc::free on the
pointer (ensuring it accepts the same pointer type), removing any use of
Box::into_raw/Box::from_raw for the byte buffer to maintain correct FFI
allocation semantics for wallet_build_and_sign_transaction and
transaction_bytes_free.
- Around line 481-483: The wallet_check_transaction FFI entry currently calls
tokio::runtime::Handle::current() (and uses serialized.into_boxed_slice() then
casts away slice metadata), which can panic outside a Tokio runtime and cause UB
when deallocating bytes; fix by switching to the same runtime pattern used in
FFIWalletManager: store an Arc<tokio::runtime::Runtime> on the wallet manager
and call runtime.block_on(managed_info.check_core_transaction(...)) instead of
Handle::current(), and change the transaction byte handling to preserve
length/metadata across the FFI boundary (e.g. pass a struct with *mut u8 plus
length or keep a Box<[u8]> and transfer it without casting to *mut u8 so you can
reconstruct with Box<[u8]>::from_raw when freeing) to avoid casting Box<[u8]> to
Box<u8> and the resulting type/size mismatch.

In `@key-wallet-ffi/src/wallet_manager.rs`:
- Around line 57-80: wallet_manager_create transfers ownership of an
FFIWalletManager to callers but no destructor is exposed; add a public extern
"C" destructor named wallet_manager_free that reverses that transfer, is safe
for null, and is usable by tests and external callers. Implement
wallet_manager_free(ptr: *mut FFIWalletManager, error: *mut FFIError) as an
extern "C" fn that returns void, checks for null, uses Box::from_raw to reclaim
the allocation, properly shuts down or drops the contained runtime and manager
(drop the Arc<RwLock<WalletManager>> and cleanly stop the
tokio::runtime::Runtime), and set FFIError success/failure via
FFIError::set_success/set_error; ensure symbol name matches wallet_manager_free
expected by tests and FFI consumers.

In `@key-wallet-ffi/src/wallet.rs`:
- Around line 400-445: The error messages in wallet_add_account that direct
callers to removed functions (wallet_add_platform_payment_account,
wallet_add_dashpay_receiving_account,
wallet_add_dashpay_external_account_with_xpub_bytes) must be replaced: update
the match arms for FFIAccountType::PlatformPayment, ::DashpayReceivingFunds and
::DashpayExternalAccount to return a neutral unsupported error (e.g.
FFIAccountResult::error with FFIErrorCode::UnsupportedOperation or InvalidInput
and a message like "Account type <X> is not supported through this FFI surface")
or, if there is a real replacement API, point to that new API instead; apply the
same change to the repeated/error paths later in the file (the other matching
blocks around the 494-547 region) so callers are not pointed at removed entry
points.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2cb33def-9e6b-4ca9-8cd3-d7e9c34fb5d9

📥 Commits

Reviewing files that changed from the base of the PR and between d9d55ef and 8ddba5f.

📒 Files selected for processing (19)
  • key-wallet-ffi/Cargo.toml
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/account.rs
  • key-wallet-ffi/src/account_collection.rs
  • key-wallet-ffi/src/account_derivation.rs
  • key-wallet-ffi/src/bip38.rs
  • key-wallet-ffi/src/derivation.rs
  • key-wallet-ffi/src/keys.rs
  • key-wallet-ffi/src/lib.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_account_collection.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/mnemonic.rs
  • key-wallet-ffi/src/transaction.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/utils.rs
  • key-wallet-ffi/src/utxo.rs
  • key-wallet-ffi/src/wallet.rs
  • key-wallet-ffi/src/wallet_manager.rs
💤 Files with no reviewable changes (5)
  • key-wallet-ffi/src/utils.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/mnemonic.rs
  • key-wallet-ffi/src/utxo.rs
  • key-wallet-ffi/src/bip38.rs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (8)
key-wallet-ffi/src/managed_wallet.rs (1)

592-606: ⚠️ Potential issue | 🔴 Critical

Update the test module or keep a managed_wallet_free alias.

managed_wallet_info_free() is now the only free function here, but this file's test module still calls managed_wallet_free() at Lines 627, 793, 980, and 1076. As written, the module won't compile once the removal lands.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/managed_wallet.rs` around lines 592 - 606, The tests still
call managed_wallet_free but the implementation now exposes
managed_wallet_info_free; either update the test module to call
managed_wallet_info_free everywhere (replace usages of managed_wallet_free in
the test module) or add a simple FFI alias named managed_wallet_free that
forwards to managed_wallet_info_free (maintain the same signature and safety
semantics) so existing tests compile; update references to the symbols
managed_wallet_free and managed_wallet_info_free accordingly.
key-wallet-ffi/src/managed_account.rs (1)

205-214: ⚠️ Potential issue | 🟡 Minor

Free the intermediate FFIError.message after copying it.

Both error paths convert error.message into a new Rust String, then allocate a second CString in FFIManagedCoreAccountResult::error(). The original FFIError.message buffer is never released, so repeated lookup failures leak memory.

💡 Suggested cleanup
-        return FFIManagedCoreAccountResult::error(
-            error.code,
-            if error.message.is_null() {
-                "Failed to get managed wallet info".to_string()
-            } else {
-                let c_str = std::ffi::CStr::from_ptr(error.message);
-                c_str.to_string_lossy().to_string()
-            },
-        );
+        let message = if error.message.is_null() {
+            "Failed to get managed wallet info".to_string()
+        } else {
+            let message = std::ffi::CStr::from_ptr(error.message)
+                .to_string_lossy()
+                .into_owned();
+            error.free_message();
+            message
+        };
+        return FFIManagedCoreAccountResult::error(error.code, message);

As per coding guidelines, **/*-ffi/**/*.rs: Handle memory safety carefully at FFI boundaries.

Also applies to: 323-332

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/managed_account.rs` around lines 205 - 214, The code is
leaking the original FFIError.message buffer after converting it to a Rust
String before calling FFIManagedCoreAccountResult::error; update the branches
where you read error.message (e.g., the managed_wallet_ptr null branch and the
similar block around lines 323-332) to copy the message into a Rust String, then
free the original FFIError.message buffer (using the matching FFI deallocator:
e.g., CString::from_raw(error.message as *mut _) or the appropriate libc::free
wrapper) before passing the copied String into
FFIManagedCoreAccountResult::error so the original C allocation is released.
key-wallet-ffi/src/wallet.rs (1)

373-387: ⚠️ Potential issue | 🔴 Critical

Preserve a const-safe wallet destructor.

wallet_manager_get_wallet() in key-wallet-ffi/src/wallet_manager.rs:494-540 still returns *const FFIWallet, so removing wallet_free_const() leaves callers with no documented/safe way to release that allocation.

💡 Minimal compatibility shim
+#[no_mangle]
+pub unsafe extern "C" fn wallet_free_const(wallet: *const FFIWallet) {
+    wallet_free(wallet as *mut FFIWallet);
+}

As per coding guidelines, **/*-ffi/**/*.rs: Handle memory safety carefully at FFI boundaries.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/wallet.rs` around lines 373 - 387, The FFI exposed
destructor removed the const-safe variant: restore a wallet_free_const function
that accepts *const FFIWallet (to match wallet_manager_get_wallet which returns
*const FFIWallet) and frees the allocation safely by checking for null, casting
the const pointer to *mut FFIWallet, and calling Box::from_raw to drop it
(mirror wallet_free behavior); keep wallet_free as-is and ensure both functions
are #[no_mangle] pub unsafe extern "C" fn with the same safety doc comment so
callers holding *const FFIWallet can release memory correctly.
key-wallet-ffi/src/transaction.rs (2)

336-340: ⚠️ Potential issue | 🔴 Critical

transaction_bytes_free is freeing the wrong allocation type.

wallet_build_and_sign_transaction() allocates a boxed slice, but transaction_bytes_free() reconstructs it as Box<u8>. That loses the slice metadata and makes the deallocation undefined behavior at the FFI boundary.

💡 One safe fix
-#[no_mangle]
-pub unsafe extern "C" fn transaction_bytes_free(tx_bytes: *mut u8) {
-    if !tx_bytes.is_null() {
-        unsafe {
-            let _ = Box::from_raw(tx_bytes);
-        }
-    }
-}
+#[no_mangle]
+pub unsafe extern "C" fn transaction_bytes_free(tx_bytes: *mut u8, tx_len: usize) {
+    if !tx_bytes.is_null() && tx_len > 0 {
+        let _ = Box::from_raw(std::ptr::slice_from_raw_parts_mut(tx_bytes, tx_len));
+    }
+}

As per coding guidelines, **/*-ffi/**/*.rs: Handle memory safety carefully at FFI boundaries.

Also applies to: 504-508

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/transaction.rs` around lines 336 - 340, The FFI allocator
in wallet_build_and_sign_transaction produces a Box<[u8]> (boxed slice) but
transaction_bytes_free reconstructs it as Box<u8>, losing slice metadata and
causing undefined behavior; update transaction_bytes_free to rebuild the boxed
slice using the raw pointer and the known length (recreate a Box<[u8]> via
from_raw on a slice created from ptr and len) and then let it drop, and apply
the same fix to the other freeing site (the similar free at the other location
referenced in the comment) so both deallocations match the original Box<[u8]>
allocation.

477-478: ⚠️ Potential issue | 🟠 Major

Pass the runtime to these FFI functions or use an owned runtime instead of relying on an ambient Tokio context.

tokio::runtime::Handle::current() panics when wallet_check_transaction() is called from a non-Tokio thread, which is the standard case for Swift/C consumers. The function signature has no way to access the runtime that exists in FFIWalletManager. Either pass a handle to the async work or create a new runtime for the operation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/transaction.rs` around lines 477 - 478, The current use of
tokio::runtime::Handle::current() in the wallet_check_transaction path causes
panics on non-Tokio threads; modify the API so the runtime is provided or
created: update wallet_check_transaction (and the FFIWalletManager boundary) to
accept a tokio::runtime::Handle or Arc<Runtime>/Runtime reference and use that
handle to block_on managed_info.check_core_transaction(&tx, context, wallet_mut,
update_state), or alternatively construct an owned Runtime
(tokio::runtime::Runtime::new()) inside wallet_check_transaction and use its
block_on; ensure the chosen approach propagates a runtime from FFIWalletManager
(or creates/drops an owned runtime) rather than calling Handle::current().
key-wallet-ffi/src/wallet_manager.rs (1)

59-80: ⚠️ Potential issue | 🔴 Critical

Keep a destructor for wallet_manager_create().

This function still returns an owning raw pointer, but the PR removes wallet_manager_free(). That turns every manager into a permanent leak, and it is already a compile blocker for existing callers (wallet_manager_free is the current pipeline failure).

💡 Minimal compatibility shim
+#[no_mangle]
+pub unsafe extern "C" fn wallet_manager_free(manager: *mut FFIWalletManager) {
+    if !manager.is_null() {
+        let _ = Box::from_raw(manager);
+    }
+}

As per coding guidelines, **/*-ffi/**/*.rs: Handle memory safety carefully at FFI boundaries.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/wallet_manager.rs` around lines 59 - 80,
wallet_manager_create returns an owning raw pointer (FFIWalletManager) but there
is no destructor anymore, causing leaks and breaking callers; add an extern "C"
fn wallet_manager_free(ptr: *mut FFIWalletManager, error: *mut FFIError) that
checks for null, wraps the pointer with Box::from_raw to drop the
FFIWalletManager (and its Arc/RwLock/runtime), and uses
FFIError::set_success(error) on success or FFIError::set_error(...,
FFIErrorCode::NullPointer, "null pointer") when ptr is null; ensure the function
signature and safety comments match other FFI functions and do not attempt to
use the freed pointer after Box::from_raw.
key-wallet-ffi/src/keys.rs (1)

9-27: ⚠️ Potential issue | 🟡 Minor

Dead code: structs with unused inner fields.

Pipeline failures indicate FFIPrivateKey, FFIPublicKey, and FFIExtendedPublicKey have unused inner fields. Since the associated FFI functions (private_key_free, public_key_free, extended_public_key_free, etc.) were removed, these structs appear to be dead code.

Consider removing these unused structs entirely, or if they're needed for future use, suppress the warnings with #[allow(dead_code)].

Option 1: Remove unused structs
-/// Opaque type for a private key (SecretKey)
-pub struct FFIPrivateKey {
-    inner: secp256k1::SecretKey,
-}
-
 /// Opaque type for an extended private key
 pub struct FFIExtendedPrivateKey {
     inner: key_wallet::bip32::ExtendedPrivKey,
 }
 
-/// Opaque type for a public key
-pub struct FFIPublicKey {
-    inner: secp256k1::PublicKey,
-}
-
-/// Opaque type for an extended public key
-pub struct FFIExtendedPublicKey {
-    inner: key_wallet::bip32::ExtendedPubKey,
-}
Option 2: Suppress warnings if needed for future use
 /// Opaque type for a private key (SecretKey)
+#[allow(dead_code)]
 pub struct FFIPrivateKey {
     inner: secp256k1::SecretKey,
 }

 /// Opaque type for a public key
+#[allow(dead_code)]
 pub struct FFIPublicKey {
     inner: secp256k1::PublicKey,
 }

 /// Opaque type for an extended public key
+#[allow(dead_code)]
 pub struct FFIExtendedPublicKey {
     inner: key_wallet::bip32::ExtendedPubKey,
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/keys.rs` around lines 9 - 27, The structs FFIPrivateKey,
FFIPublicKey, and FFIExtendedPublicKey are flagged for dead code because their
inner fields are unused; either delete these struct definitions entirely (remove
FFIPrivateKey, FFIPublicKey, FFIExtendedPublicKey from keys.rs and any unused
references) or mark them as intentionally unused by adding #[allow(dead_code)]
above each struct declaration; keep FFIExtendedPrivateKey untouched if it is
still used. Ensure any associated functions/FFI symbols referencing these
structs are also removed or updated to avoid dangling references.
key-wallet-ffi/src/account_collection.rs (1)

300-579: ⚠️ Potential issue | 🔴 Critical

Tests reference undefined functions — compilation will fail.

The test module (lines 307–579 in the provided snippet) calls functions that are not defined in this file:

  • account_collection_count (line 326)
  • account_collection_get_bip44_indices (line 333)
  • account_collection_get_bip44_account (line 338)
  • free_u32_array (line 344)
  • account_collection_has_provider_operator_keys (line 380)
  • account_collection_has_provider_platform_keys (line 426)
  • account_collection_get_provider_platform_keys (line 428)
  • account_collection_summary (lines 496, 554, 576)

The actual API provides account_collection_summary_data and account_collection_summary_free. Either update these tests to use the correct functions or remove them if they are obsolete.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-ffi/src/account_collection.rs` around lines 300 - 579, The tests
call several undefined functions; update the test code to use the real API or
remove obsolete calls: replace account_collection_summary(...) usages with
account_collection_summary_data(...) and then free the returned summary via
account_collection_summary_free(...); for account_collection_count,
account_collection_get_bip44_indices, account_collection_get_bip44_account,
account_collection_has_provider_operator_keys,
account_collection_has_provider_platform_keys,
account_collection_get_provider_platform_keys and free_u32_array either change
the tests to call the corresponding real functions from the public API (or their
correct crate::... paths) or remove those assertions if those helpers no longer
exist—ensure any new summary/data pointer is converted via CStr::from_ptr and
freed with account_collection_summary_free to avoid leaks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@key-wallet-ffi/src/account_collection.rs`:
- Around line 300-579: The tests call several undefined functions; update the
test code to use the real API or remove obsolete calls: replace
account_collection_summary(...) usages with account_collection_summary_data(...)
and then free the returned summary via account_collection_summary_free(...); for
account_collection_count, account_collection_get_bip44_indices,
account_collection_get_bip44_account,
account_collection_has_provider_operator_keys,
account_collection_has_provider_platform_keys,
account_collection_get_provider_platform_keys and free_u32_array either change
the tests to call the corresponding real functions from the public API (or their
correct crate::... paths) or remove those assertions if those helpers no longer
exist—ensure any new summary/data pointer is converted via CStr::from_ptr and
freed with account_collection_summary_free to avoid leaks.

In `@key-wallet-ffi/src/keys.rs`:
- Around line 9-27: The structs FFIPrivateKey, FFIPublicKey, and
FFIExtendedPublicKey are flagged for dead code because their inner fields are
unused; either delete these struct definitions entirely (remove FFIPrivateKey,
FFIPublicKey, FFIExtendedPublicKey from keys.rs and any unused references) or
mark them as intentionally unused by adding #[allow(dead_code)] above each
struct declaration; keep FFIExtendedPrivateKey untouched if it is still used.
Ensure any associated functions/FFI symbols referencing these structs are also
removed or updated to avoid dangling references.

In `@key-wallet-ffi/src/managed_account.rs`:
- Around line 205-214: The code is leaking the original FFIError.message buffer
after converting it to a Rust String before calling
FFIManagedCoreAccountResult::error; update the branches where you read
error.message (e.g., the managed_wallet_ptr null branch and the similar block
around lines 323-332) to copy the message into a Rust String, then free the
original FFIError.message buffer (using the matching FFI deallocator: e.g.,
CString::from_raw(error.message as *mut _) or the appropriate libc::free
wrapper) before passing the copied String into
FFIManagedCoreAccountResult::error so the original C allocation is released.

In `@key-wallet-ffi/src/managed_wallet.rs`:
- Around line 592-606: The tests still call managed_wallet_free but the
implementation now exposes managed_wallet_info_free; either update the test
module to call managed_wallet_info_free everywhere (replace usages of
managed_wallet_free in the test module) or add a simple FFI alias named
managed_wallet_free that forwards to managed_wallet_info_free (maintain the same
signature and safety semantics) so existing tests compile; update references to
the symbols managed_wallet_free and managed_wallet_info_free accordingly.

In `@key-wallet-ffi/src/transaction.rs`:
- Around line 336-340: The FFI allocator in wallet_build_and_sign_transaction
produces a Box<[u8]> (boxed slice) but transaction_bytes_free reconstructs it as
Box<u8>, losing slice metadata and causing undefined behavior; update
transaction_bytes_free to rebuild the boxed slice using the raw pointer and the
known length (recreate a Box<[u8]> via from_raw on a slice created from ptr and
len) and then let it drop, and apply the same fix to the other freeing site (the
similar free at the other location referenced in the comment) so both
deallocations match the original Box<[u8]> allocation.
- Around line 477-478: The current use of tokio::runtime::Handle::current() in
the wallet_check_transaction path causes panics on non-Tokio threads; modify the
API so the runtime is provided or created: update wallet_check_transaction (and
the FFIWalletManager boundary) to accept a tokio::runtime::Handle or
Arc<Runtime>/Runtime reference and use that handle to block_on
managed_info.check_core_transaction(&tx, context, wallet_mut, update_state), or
alternatively construct an owned Runtime (tokio::runtime::Runtime::new()) inside
wallet_check_transaction and use its block_on; ensure the chosen approach
propagates a runtime from FFIWalletManager (or creates/drops an owned runtime)
rather than calling Handle::current().

In `@key-wallet-ffi/src/wallet_manager.rs`:
- Around line 59-80: wallet_manager_create returns an owning raw pointer
(FFIWalletManager) but there is no destructor anymore, causing leaks and
breaking callers; add an extern "C" fn wallet_manager_free(ptr: *mut
FFIWalletManager, error: *mut FFIError) that checks for null, wraps the pointer
with Box::from_raw to drop the FFIWalletManager (and its Arc/RwLock/runtime),
and uses FFIError::set_success(error) on success or FFIError::set_error(...,
FFIErrorCode::NullPointer, "null pointer") when ptr is null; ensure the function
signature and safety comments match other FFI functions and do not attempt to
use the freed pointer after Box::from_raw.

In `@key-wallet-ffi/src/wallet.rs`:
- Around line 373-387: The FFI exposed destructor removed the const-safe
variant: restore a wallet_free_const function that accepts *const FFIWallet (to
match wallet_manager_get_wallet which returns *const FFIWallet) and frees the
allocation safely by checking for null, casting the const pointer to *mut
FFIWallet, and calling Box::from_raw to drop it (mirror wallet_free behavior);
keep wallet_free as-is and ensure both functions are #[no_mangle] pub unsafe
extern "C" fn with the same safety doc comment so callers holding *const
FFIWallet can release memory correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba110343-51de-40e3-9c0f-33d4163aa08d

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddba5f and ee4fffe.

📒 Files selected for processing (19)
  • key-wallet-ffi/Cargo.toml
  • key-wallet-ffi/include/key_wallet_ffi.h
  • key-wallet-ffi/src/account.rs
  • key-wallet-ffi/src/account_collection.rs
  • key-wallet-ffi/src/account_derivation.rs
  • key-wallet-ffi/src/bip38.rs
  • key-wallet-ffi/src/derivation.rs
  • key-wallet-ffi/src/keys.rs
  • key-wallet-ffi/src/lib.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_account_collection.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/mnemonic.rs
  • key-wallet-ffi/src/transaction.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/utils.rs
  • key-wallet-ffi/src/utxo.rs
  • key-wallet-ffi/src/wallet.rs
  • key-wallet-ffi/src/wallet_manager.rs
💤 Files with no reviewable changes (5)
  • key-wallet-ffi/src/utxo.rs
  • key-wallet-ffi/src/utils.rs
  • key-wallet-ffi/src/types.rs
  • key-wallet-ffi/src/bip38.rs
  • key-wallet-ffi/src/mnemonic.rs

@ZocoLini ZocoLini marked this pull request as draft March 12, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant