diff --git a/Cargo.lock b/Cargo.lock index 11f0cb7e..9204fc28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6745,6 +6745,7 @@ dependencies = [ "cbindgen", "common", "nssa", + "nssa_core", "tempfile", "tokio", "wallet", diff --git a/integration_tests/tests/wallet_ffi.rs b/integration_tests/tests/wallet_ffi.rs index 4599a79e..51cb31bb 100644 --- a/integration_tests/tests/wallet_ffi.rs +++ b/integration_tests/tests/wallet_ffi.rs @@ -5,7 +5,7 @@ use std::{ }; use anyhow::Result; -use integration_tests::{ACC_SENDER, TestContext}; +use integration_tests::{ACC_SENDER, ACC_SENDER_PRIVATE, TestContext}; use log::info; use nssa::{Account, AccountId, PublicKey, program::Program}; use tempfile::tempdir; @@ -65,6 +65,8 @@ unsafe extern "C" { account_id: *const FfiBytes32, out_keys: *mut FfiPrivateAccountKeys, ) -> error::WalletFfiError; + + fn wallet_ffi_free_private_account_keys(keys: *mut FfiPrivateAccountKeys); } fn new_wallet_ffi_with_test_context_config(ctx: &TestContext) -> *mut WalletHandle { @@ -377,34 +379,41 @@ fn test_wallet_ffi_get_public_account_keys() -> Result<()> { Ok(()) } -// #[test] -// fn test_wallet_ffi_get_private_account_keys() -> Result<()> { -// let ctx = TestContext::new_blocking()?; -// let account_id: AccountId = ACC_SENDER.parse().unwrap(); -// let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx); -// let mut out_key = FfiPrivateAccountKeys::default(); -// -// let key: PublicKey = unsafe { -// let ffi_account_id = FfiBytes32::from(&account_id); -// let _result = wallet_ffi_get_private_account_keys( -// wallet_ffi_handle, -// (&ffi_account_id) as *const FfiBytes32, -// (&mut out_key) as *mut FfiPublicAccountKey, -// ); -// (&out_key).try_into().unwrap() -// }; -// -// let expected_key = { -// let private_key = ctx -// .wallet() -// .get_account_public_signing_key(&account_id) -// .unwrap(); -// PublicKey::new_from_private_key(private_key) -// }; -// -// assert_eq!(key, expected_key); -// -// info!("Successfully retrieved account key"); -// -// Ok(()) -// } +#[test] +fn test_wallet_ffi_get_private_account_keys() -> Result<()> { + let ctx = TestContext::new_blocking()?; + let account_id: AccountId = ACC_SENDER_PRIVATE.parse().unwrap(); + let wallet_ffi_handle = new_wallet_ffi_with_test_context_config(&ctx); + let mut keys = FfiPrivateAccountKeys::default(); + + unsafe { + let ffi_account_id = FfiBytes32::from(&account_id); + let _result = wallet_ffi_get_private_account_keys( + wallet_ffi_handle, + (&ffi_account_id) as *const FfiBytes32, + (&mut keys) as *mut FfiPrivateAccountKeys, + ); + }; + + let key_chain = &ctx + .wallet() + .storage() + .user_data + .get_private_account(&account_id) + .unwrap() + .0; + + let expected_npk = &key_chain.nullifer_public_key; + let expected_ivk = &key_chain.incoming_viewing_public_key; + + assert_eq!(&keys.npk(), expected_npk); + assert_eq!(&keys.ivk().unwrap(), expected_ivk); + + unsafe { + wallet_ffi_free_private_account_keys((&mut keys) as *mut FfiPrivateAccountKeys); + } + + info!("Successfully retrieved account keys"); + + Ok(()) +} diff --git a/wallet-ffi/Cargo.toml b/wallet-ffi/Cargo.toml index c02e58ee..109d9e5b 100644 --- a/wallet-ffi/Cargo.toml +++ b/wallet-ffi/Cargo.toml @@ -10,6 +10,7 @@ crate-type = ["rlib", "cdylib", "staticlib"] wallet.workspace = true nssa.workspace = true common.workspace = true +nssa_core.workspace = true tokio.workspace = true [build-dependencies] diff --git a/wallet-ffi/src/error.rs b/wallet-ffi/src/error.rs index 3cae2f25..d2f615c3 100644 --- a/wallet-ffi/src/error.rs +++ b/wallet-ffi/src/error.rs @@ -38,6 +38,8 @@ pub enum WalletFfiError { SerializationError = 14, /// Invalid conversion from FFI types to NSSA types InvalidTypeConversion, + /// Invalid Key value + InvalidKeyValue, /// Internal error (catch-all) InternalError = 99, } diff --git a/wallet-ffi/src/types.rs b/wallet-ffi/src/types.rs index dea1ac94..a1d70181 100644 --- a/wallet-ffi/src/types.rs +++ b/wallet-ffi/src/types.rs @@ -4,6 +4,7 @@ use core::slice; use std::{ffi::c_char, ptr}; use nssa::{Account, Data}; +use nssa_core::encryption::shared_key_derivation::Secp256k1Point; use crate::error::WalletFfiError; @@ -150,6 +151,26 @@ impl FfiBytes32 { } } +impl FfiPrivateAccountKeys { + pub fn npk(&self) -> nssa_core::NullifierPublicKey { + nssa_core::NullifierPublicKey(self.nullifier_public_key.data) + } + + pub fn ivk(&self) -> Result { + if self.incoming_viewing_public_key_len == 33 { + let slice = unsafe { + slice::from_raw_parts( + self.incoming_viewing_public_key, + self.incoming_viewing_public_key_len, + ) + }; + Ok(Secp256k1Point(slice.to_vec())) + } else { + Err(WalletFfiError::InvalidKeyValue) + } + } +} + impl From for FfiU128 { fn from(value: u128) -> Self { Self { diff --git a/wallet-ffi/wallet_ffi.h b/wallet-ffi/wallet_ffi.h index e731db79..afab46e1 100644 --- a/wallet-ffi/wallet_ffi.h +++ b/wallet-ffi/wallet_ffi.h @@ -99,6 +99,10 @@ typedef enum WalletFfiError { * Invalid conversion from FFI types to NSSA types */ INVALID_TYPE_CONVERSION, + /** + * Invalid Key value + */ + INVALID_KEY_VALUE, /** * Internal error (catch-all) */