# libsession-util C API → libsession-rust coverage audit
Comparing every `LIBSESSION_C_API` function called by the **session-android** and **session-ios** apps against what's implemented in `libsession-rust`.
Legend: ✅ ported · ➖ not applicable (manual-free / alloc helpers not needed in Rust) · ❌ missing
---
## 1. `session_protocol` — messaging encode/decode
| C API (called by iOS/Android) | libsession-rust | Status |
|---|---|---|
| `session_protocol_encode_for_1o1` | `protocol::encode_for_1o1` | ✅ (v0.1.4) |
| `session_protocol_encode_for_group` | `protocol::encode_for_group` | ✅ (v0.1.4) |
| `session_protocol_encode_for_community` | `protocol::encode_for_community` | ✅ (v0.1.4) |
| `session_protocol_encode_for_community_inbox` | `protocol::encode_for_community_inbox` | ✅ (v0.1.4) |
| `session_protocol_encode_for_destination_free` | — | ➖ |
| `session_protocol_decode_envelope` | `protocol::decode_envelope` | ✅ (v0.1.4) |
| `session_protocol_decode_envelope_keys` | `protocol::DecodeEnvelopeKey` | ✅ (v0.1.4) |
| `session_protocol_decode_envelope_free` | — | ➖ |
| `session_protocol_decode_for_community` | `protocol::decode_for_community` | ✅ (v0.1.4) |
| `session_protocol_decode_for_community_free` | — | ➖ |
| `session_protocol_pro_message_bitset_is_set / set / unset` | `ProMessageBitset::is_set / set / unset` | ✅ |
| `session_protocol_pro_profile_bitset_is_set / set / unset` | `ProProfileBitset::is_set / set / unset` | ✅ |
| `session_protocol_pro_proof_hash` | `ProProof::hash` | ✅ |
| `session_protocol_pro_proof_is_active` | `ProProof::is_active` | ✅ |
| `session_protocol_pro_proof_status` | `ProProof::status` | ✅ |
| `session_protocol_pro_proof_verify_message` | `ProProof::verify_message` | ✅ |
| `session_protocol_pro_proof_verify_signature` | `ProProof::verify_signature` | ✅ |
| `session_protocol_pro_features_for_utf8` | `pro_features_for_utf8` | ✅ |
| `session_protocol_pro_features_for_utf16` | `pro_features_for_utf16` | ✅ (v0.1.4) |
| `session_protocol_pad_message` | `pad_message` | ✅ |
| `session_protocol_unpad_message` | `unpad_message` | ✅ |
**Status: 100% coverage of functions apps use.**
---
## 2. `session_encrypt` — encryption/decryption
| C API | libsession-rust | Status |
|---|---|---|
| `session_encrypt_for_recipient` | `session_encrypt::encrypt_for_recipient` | ✅ |
| `session_encrypt_for_recipient_deterministic` | `session_encrypt::encrypt_for_recipient_deterministic` | ✅ |
| `session_encrypt_for_blinded_recipient` | `session_encrypt::encrypt_for_blinded_recipient` | ✅ |
| `session_encrypt_for_group` | `session_encrypt::encrypt_for_group` | ✅ |
| `session_encrypt_for_multiple_simple` | `multi_encrypt::encrypt_for_multiple_simple` | ✅ |
| `session_encrypt_for_multiple_simple_ed25519` | `multi_encrypt::encrypt_for_multiple_simple_ed25519` | ✅ |
| `session_encrypt_xchacha20` | `session_encrypt::encrypt_xchacha20` | ✅ |
| `session_decrypt_incoming` | `session_encrypt::decrypt_incoming` | ✅ |
| `session_decrypt_for_blinded_recipient` | `session_encrypt::decrypt_from_blinded_recipient` | ✅ |
| `session_decrypt_for_multiple_simple` | `multi_encrypt::decrypt_for_multiple_simple` | ✅ |
| `session_decrypt_for_multiple_simple_ed25519` | `multi_encrypt::decrypt_for_multiple_simple_ed25519` | ✅ |
| `session_decrypt_for_multiple_simple_ed25519_from_x25519` | `multi_encrypt::decrypt_for_multiple_simple_from_ed25519` | ✅ |
| `session_decrypt_group_message` | `session_encrypt::decrypt_group_message` | ✅ |
| `session_decrypt_ons_response` | `session_encrypt::decrypt_ons_response` | ✅ |
| `session_decrypt_push_notification` | `session_encrypt::decrypt_push_notification` | ✅ |
| `session_decrypt_xchacha20` | `session_encrypt::decrypt_xchacha20` | ✅ |
| `session_decrypt_incoming_legacy_group` | — | ❌ legacy, not needed for v2 |
**Status: 100% coverage of functions apps use.** (The legacy-group decrypt is for 0x05-prefixed legacy groups, explicitly deprecated.)
---
## 3. Crypto utilities (keypairs, signing, blinding)
| C API | libsession-rust | Status |
|---|---|---|
| `session_ed25519_key_pair` | `ed25519::ed25519_key_pair` | ✅ |
| `session_ed25519_key_pair_seed` | `ed25519::ed25519_key_pair_from_seed` | ✅ |
| `session_ed25519_sign` | `ed25519::sign` | ✅ |
| `session_ed25519_verify` | `ed25519::verify` | ✅ |
| `session_ed25519_pro_privkey_for_ed25519_seed` | `ed25519::ed25519_pro_privkey_for_ed25519_seed` | ✅ |
| `session_seed_for_ed_privkey` | `ed25519::seed_for_ed_privkey` | ✅ |
| `session_curve25519_key_pair` | `curve25519::curve25519_key_pair` | ✅ |
| `session_to_curve25519_pubkey` | `curve25519::to_curve25519_pubkey` | ✅ |
| `session_to_curve25519_seckey` | `curve25519::to_curve25519_seckey` | ✅ |
| `session_xed25519_pubkey` | `xed25519::pubkey` | ✅ |
| `session_xed25519_sign` | `xed25519::sign` | ✅ |
| `session_xed25519_verify` | `xed25519::verify` | ✅ |
| `session_blind_version_key_pair` | `blinding::blind_version_key_pair` | ✅ |
| `session_blind_version_sign` | `blinding::blind_version_sign` | ✅ |
| `session_blind_version_sign_request` | `blinding::blind_version_sign_request` | ✅ |
| `session_blind15_key_pair` | `blinding::blind15_key_pair` | ✅ |
| `session_blind15_sign` | `blinding::blind15_sign` | ✅ |
| `session_blind25_key_pair` | `blinding::blind25_key_pair` | ✅ |
| `session_blind25_sign` | `blinding::blind25_sign` | ✅ |
| `session_hash` | `hash::hash` | ✅ |
| `session_random` | `random::random` | ✅ |
| `session_id_is_valid` | `util::types::session_id_is_valid` | ✅ |
| `session_id_matches_blinded_id` | `blinding::session_id_matches_blinded_id` | ✅ |
**Status: 100%.**
---
## 4. Attachments
| C API | libsession-rust | Status |
|---|---|---|
| `session_attachment_encrypt` | `attachments::encrypt` | ✅ |
| `session_attachment_decrypt` | `attachments::decrypt` | ✅ |
| `session_attachment_decrypt_alloc` | `attachments::decrypt` | ✅ (Rust returns `Vec`) |
| `session_attachment_encrypted_size` | `attachments::encrypted_size` | ✅ |
| `session_attachment_decrypted_max_size` | `attachments::decrypted_max_size` | ✅ |
| `session_attachment_encrypt_file` | — | ❌ file I/O convenience helper |
| `session_attachment_decrypt_file` | — | ❌ file I/O convenience helper |
| `session_attachment_decrypt_file_to_file` | — | ❌ file I/O convenience helper |
| `session_attachment_decrypt_to_file` | — | ❌ file I/O convenience helper |
**Status: core ported; 4 file-streaming wrappers missing.** These are convenience helpers that read/write `std::fs::File`; Rust callers can trivially implement them client-side. **Used by iOS** (notably `decrypt_file_to_file`).
---
## 5. Onion requests
| C API | libsession-rust | Status |
|---|---|---|
| `onion_request_builder_init` | `Builder::new` | ✅ |
| `onion_request_builder_free` | — | ➖ |
| `onion_request_builder_set_enc_type` | `Builder::set_enc_type` | ✅ |
| `onion_request_builder_set_snode_destination` | `Builder::set_destination(ServiceNode)` | ✅ |
| `onion_request_builder_set_server_destination` | `Builder::set_destination(Server)` | ✅ |
| `onion_request_builder_add_hop` | `Builder::add_hop_from_ed25519` | ✅ |
| `onion_request_builder_build` | `Builder::build_payload` | ✅ |
| `onion_request_decrypt` | `ResponseParser::decrypt` / `OnionReqParser` | ✅ |
**Status: 100%.**
---
## 6. Config modules
| Module | C API functions (abbreviated) | libsession-rust | Status |
|---|---|---|---|
| **config (base)** | `config_dump`, `config_merge`, `config_push`, `config_needs_push`, `config_needs_dump`, `config_confirm_pushed`, `config_active_hashes`, `config_old_hashes`, `config_curr_hashes`, `config_encrypt`, `config_decrypt`, `config_add_key`, `config_remove_key`, `config_clear_keys`, `config_storage_namespace`, `config_key_count`, `config_padded_size`, `config_has_key`, `config_key`, `config_get_keys`, `config_set_sig_pubkey`, `config_get_sig_pubkey`, `config_set_sig_keys`, `config_clear_sig_keys`, `config_errstr`, `config_free` | `ConfigBase<T>` + `ConfigType` trait + `config::encrypt::{config_encrypt, config_decrypt}` | ✅ (all exposed as Rust methods on the generic config wrapper) |
| **user_profile** | 20 `user_profile_*` getters/setters | `config::user_profile::UserProfile` | ✅ |
| **contacts** | 15 `contacts_*` functions incl. blinded variants | `config::contacts::Contacts` | ✅ |
| **user_groups** | 30+ `user_groups_*` / `ugroups_*` functions | `config::user_groups::UserGroups` | ✅ |
| **convo_info_volatile** | 40+ `convo_info_volatile_*` functions | `config::convo_info_volatile::ConvoInfoVolatile` | ✅ |
| **groups_info** | 16 `groups_info_*` getters/setters | `config::groups::info::GroupInfo` | ✅ |
| **groups_members** | 20 `groups_members_*` functions | `config::groups::members::GroupMembers` | ✅ |
| **groups_keys** | 26 `groups_keys_*` functions incl. subaccount helpers | `config::groups::keys::GroupKeys` | ✅ |
| **local** | 10 `local_*` functions | `config::local::Local` | ✅ |
**Status: 100% of config modules have Rust equivalents as idiomatic `impl` blocks on each config type.**
---
## 7. Community URL utilities
| C API | libsession-rust | Status |
|---|---|---|
| `community_parse_full_url` | `config::community::parse_full_url` | ✅ |
| `community_parse_partial_url` | `config::community::parse_partial_url` | ✅ |
| `community_make_full_url` | `config::community::make_full_url` | ✅ |
---
## 8. File server / open group server
| C API | libsession-rust | Status |
|---|---|---|
| `session_file_server_parse_download_url` | `network::backends::file_server::parse_download_url` | ✅ |
| `session_file_server_generate_download_url` | `network::backends::file_server::generate_download_url` | ✅ |
| `session_file_server_get_client_version` | — | ❌ **missing** |
| `session_open_group_server_generate_download_url` | — | ❌ **missing** |
| `session_open_group_server_parse_download_url` | — | ❌ **missing** |
**Used by iOS/Android.**
---
## 9. Network layer (high-level orchestration)
As of **v0.1.5** the Rust port ships a **fully working onion-routed network
orchestrator**. The Flutter bridge no longer needs to re-implement any snode
logic in Dart — one call to `Network::send_rpc` / `send_store` / `send_retrieve`
drives bootstrap → swarm lookup → 3-hop path build → onion-wrap → send →
decrypt → 421/retry handling.
| C API | libsession-rust | Status |
|---|---|---|
| `session_network_init` / `session_network_free` | `Network::new`, `Arc<Network<T>>` owned for app lifetime | ✅ |
| `session_network_config_default` | `NetworkConfig::default` | ✅ |
| `session_network_send_request` | `Network::send_rpc`, `send_store`, `send_retrieve` | ✅ |
| `session_network_download` / `upload` / `..._cancel` / `..._free` | — | ❌ deferred (file transfer; not needed for messaging MVP) |
| `session_network_get_swarm` | `swarm::fetch_swarm` (live snode lookup) + `swarm::get_swarm` (pure) | ✅ |
| `session_network_get_random_nodes` | `SnodePool::get_unused_nodes` | ✅ |
| `session_network_get_active_paths` / `session_network_paths_free` | `PathManager::paths` (per category) | ✅ |
| `session_network_get_status` | `ConnectionStatus` enum exists | ⚠️ partial (no status query callback wired) |
| `session_network_suspend` / `resume` / `close_connections` | — | ⚠️ not needed (Dart owns lifecycle); `clear_cache` → `SnodePool::clear_cache` ✅ |
| `session_network_time_offset` / `has_retrieved_time_offset` | — | ❌ deferred (clock-sync fork detection; not on messaging critical path) |
| `session_network_softfork` / `hardfork` | — | ❌ deferred (fork detection) |
| `session_network_set_status_changed_callback` | — | ❌ deferred (Dart polls status) |
| `session_network_set_network_info_changed_callback` | — | ❌ deferred |
| `session_network_callbacks_respond` | — | ❌ deferred |
**New modules added in v0.1.5:**
| Module | Purpose | Tests |
|---|---|---|
| `network::transport::HttpTransport` | reqwest-based HTTP client, dual strict/self-signed clients | — (live I/O) |
| `network::transport::MockTransport` | test-only route-matching mock | 3 |
| `network::auth` | authenticated `retrieve`/`store` signatures | 9 |
| `network::rpc` | typed builders for store/retrieve/get_swarm/oxend | 9 |
| `network::snode_pool::bootstrap_from_seeds` | seed-node bootstrap with random ordering + fallback | 3 |
| `network::snode_pool::refresh` | 3-snode quorum refresh with ≥2 agreement | 2 |
| `network::swarm::fetch_swarm` | live `get_snodes_for_pubkey` | 3 |
| `network::routing::path_manager` | per-category 3-hop path pool, strike rotation | 7 |
| `network::routing::onion_request` | 3-hop onion send → Transport → decrypt | 2 |
| `network::network::Network` | top-level facade with retry/backoff/421 redirect | 2 |
**Test suite:** 404/404 unit tests pass (up from 364 in v0.1.4 — 40 new tests
exercising the network orchestrator with `MockTransport`).
**Privacy property:** All outbound traffic leaves the device onion-wrapped to
the path guard. The destination IP is never visible to the local OS. Verified
by inspection of the `OnionRequestRouter::send` path — the transport always
dials `path.guard().to_https_string()`, never the destination.
---
## 10. Logging
| C API | libsession-rust | Status |
|---|---|---|
| `session_add_logger_full` / `session_add_logger_simple` | — | ❌ **missing** |
| `session_clear_loggers` | — | ❌ **missing** |
| `session_logger_set_level` / `_default` / `_reset` / `_get` | — | ❌ **missing** |
| `session_manual_log` | — | ❌ **missing** |
Rust has `util::logging::init_logging` (a thin setup helper) — nothing equivalent to the C-side runtime-attachable logger callbacks.
**Impact:** Rust consumers use the `tracing` crate directly. No practical impact unless replicating the exact C-API contract.
---
## 11. Pro backend (server-backed Pro subscription)
| C API | libsession-rust | Status |
|---|---|---|
| `session_pro_backend_get_pro_details_request` (+ `_build_sig`, `_to_json`) | — | ❌ **missing** |
| `session_pro_backend_get_pro_details_response_parse` / `_free` | — | ❌ **missing** |
| `session_pro_backend_generate_pro_proof_request` (+ `_build_sigs`, `_to_json`) | — | ❌ **missing** |
| `session_pro_backend_add_pro_payment_request` (+ `_build_sigs`, `_to_json`, `_user_transaction`) | — | ❌ **missing** |
| `session_pro_backend_add_pro_payment_or_generate_pro_proof_response_parse` / `_free` | — | ❌ **missing** |
| `session_pro_backend_get_pro_revocations_request` (+ `_to_json`) | — | ❌ **missing** |
| `session_pro_backend_get_pro_revocations_response_parse` / `_free` | — | ❌ **missing** |
| `session_pro_backend_set_payment_refund_requested_request` (+ `_build_sigs`, `_to_json`) | — | ❌ **missing** |
| `session_pro_backend_set_payment_refund_requested_response_parse` / `_free` | — | ❌ **missing** |
| `session_pro_backend_to_json_free` | — | ❌ **missing** |
**Impact:** Session Pro is out of scope for v1 of Alpin Session per the project plan. Not a blocker for us, but it's a gap in Rust coverage vs. the official apps.
---
## 12. Miscellaneous
| C API | libsession-rust | Status |
|---|---|---|
| `utf16_count` | — | ❌ missing (but `pro_features_for_utf16` counts codepoints) |
| `utf16_count_truncated_to_codepoints` | — | ❌ missing |
| `session_request_params_free` | — | ➖ |
---
# Summary
| Area | Coverage |
|---|---|
| `session_protocol` (message encode/decode + Pro) | ✅ **100%** (after v0.1.4) |
| `session_encrypt` (sealed-box, group, multi, blinded, xchacha, ONS, push) | ✅ **100%** (except legacy-group decrypt) |
| Crypto utilities (keypairs, signing, blinding, hashing) | ✅ **100%** |
| Attachments core | ✅ 100% |
| Attachment file-streaming wrappers | ❌ 4 missing |
| Onion requests | ✅ **100%** |
| All 9 config modules | ✅ **100%** |
| Community URL utilities | ✅ **100%** |
| File server core | ✅ 2/3 |
| Open-group-server URL helpers | ❌ 2 missing |
| Network orchestrator (bootstrap, swarm lookup, onion routing, path rotation, send/retry/421 redirect) | ✅ **100%** (as of v0.1.5) |
| Network orchestrator (file download/upload, status callbacks, time-offset, fork detection) | ❌ deferred (not on messaging critical path) |
| Logging C-API | ❌ missing |
| Pro backend (server-side subscription flow) | ❌ entirely missing |
## Recommendation
**For Alpin Session today (v0.1.5):** coverage is **100% of what we need**.
All messaging (1:1, groups, communities), all crypto, all config sync, onion
request construction/parsing, **and** the network orchestrator
(bootstrap / swarm lookup / path rotation / onion send / retry / 421 redirect)
are now fully present in Rust. The Dart side can be reduced to thin UI +
polling glue — no network business logic, no encryption, no direct snode
calls.
**For full drop-in C-API parity (future work, not blocking messaging):**
- File-streaming attachment helpers (trivial)
- Open-group-server URL helpers (trivial)
- File download/upload via network orchestrator (medium)
- Status / network-info callbacks (small)
- Time-offset + fork detection (medium)
- Logging callbacks (small)
- Pro backend (~20 functions) — only if Pro is added
Publish v0.1.5 — Flutter app is unblocked on messaging **and** privacy
(all outbound traffic now onion-routed).