diff options
| author | sneurlax <sneurlax@gmail.com> | 2024-10-14 21:35:00 -0500 |
|---|---|---|
| committer | sneurlax <sneurlax@gmail.com> | 2024-10-14 21:35:00 -0500 |
| commit | 774091b550cac6df4f25127adb4047cf4334b973 (patch) | |
| tree | d39b91a2f5c719c93f47c6125aa8bd5a482686d5 /impls/monero.rs/src/lib.rs | |
| parent | a046d9002345918bc39dd53c8b13885b2db84263 (diff) | |
do not use libloading
Diffstat (limited to 'impls/monero.rs/src/lib.rs')
| -rw-r--r-- | impls/monero.rs/src/lib.rs | 172 |
1 files changed, 29 insertions, 143 deletions
diff --git a/impls/monero.rs/src/lib.rs b/impls/monero.rs/src/lib.rs index c9b1d81..7cc334c 100644 --- a/impls/monero.rs/src/lib.rs +++ b/impls/monero.rs/src/lib.rs @@ -1,21 +1,9 @@ use std::ffi::{CStr, CString}; -use std::os::raw::{c_char, c_int, c_void}; -use std::path::PathBuf; +use std::os::raw::{c_int, c_void}; use std::ptr::NonNull; use std::sync::Arc; -use libloading::{Library, Symbol}; - -#[cfg(target_os = "android")] -const LIB_NAME: &str = "libmonero_libwallet2_api_c.so"; -#[cfg(target_os = "ios")] -const LIB_NAME: &str = "MoneroWallet.framework/MoneroWallet"; -#[cfg(target_os = "linux")] -const LIB_NAME: &str = "monero_libwallet2_api_c.so"; -#[cfg(target_os = "macos")] -const LIB_NAME: &str = "monero_libwallet2_api_c.dylib"; -#[cfg(target_os = "windows")] -const LIB_NAME: &str = "monero_libwallet2_api_c.dll"; +mod bindings; pub mod network { use std::os::raw::c_int; @@ -29,32 +17,25 @@ pub enum WalletError { NullPointer, FfiError(String), WalletErrorCode(c_int, String), - LibraryLoadError(String), } pub type WalletResult<T> = Result<T, WalletError>; pub struct WalletManager { ptr: NonNull<c_void>, - library: Library, } impl WalletManager { - /// Creates a new `WalletManager`, loading the Monero wallet library (`wallet2_api_c`). - pub fn new(lib_path: Option<&str>) -> WalletResult<Arc<Self>> { - let library = Self::load_library(lib_path)?; - + /// Creates a new `WalletManager` using the statically linked `MONERO_WalletManagerFactory_getWalletManager`. + pub fn new() -> WalletResult<Arc<Self>> { unsafe { - let func: Symbol<unsafe extern "C" fn() -> *mut c_void> = library - .get(b"MONERO_WalletManagerFactory_getWalletManager\0") - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; - - let ptr = NonNull::new(func()).ok_or(WalletError::NullPointer)?; - - Ok(Arc::new(WalletManager { ptr, library })) + let ptr = bindings::MONERO_WalletManagerFactory_getWalletManager(); + let ptr = NonNull::new(ptr).ok_or(WalletError::NullPointer)?; + Ok(Arc::new(WalletManager { ptr })) } } + /// Creates a new wallet. pub fn create_wallet( self: &Arc<Self>, path: &str, @@ -62,28 +43,12 @@ impl WalletManager { language: &str, network_type: c_int, ) -> WalletResult<Wallet> { - let c_path = CString::new(path) - .map_err(|_| WalletError::FfiError("Invalid path".to_string()))?; - let c_password = CString::new(password) - .map_err(|_| WalletError::FfiError("Invalid password".to_string()))?; - let c_language = CString::new(language) - .map_err(|_| WalletError::FfiError("Invalid language".to_string()))?; + let c_path = CString::new(path).map_err(|_| WalletError::FfiError("Invalid path".to_string()))?; + let c_password = CString::new(password).map_err(|_| WalletError::FfiError("Invalid password".to_string()))?; + let c_language = CString::new(language).map_err(|_| WalletError::FfiError("Invalid language".to_string()))?; unsafe { - let func: Symbol< - unsafe extern "C" fn( - *mut c_void, - *const c_char, - *const c_char, - *const c_char, - c_int, - ) -> *mut c_void, - > = self - .library - .get(b"MONERO_WalletManager_createWallet\0") - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; - - let wallet_ptr = func( + let wallet_ptr = bindings::MONERO_WalletManager_createWallet( self.ptr.as_ptr(), c_path.as_ptr(), c_password.as_ptr(), @@ -92,62 +57,10 @@ impl WalletManager { ); NonNull::new(wallet_ptr) - .map(|ptr| Wallet { - ptr, - manager: Arc::clone(self), - }) + .map(|ptr| Wallet { ptr, manager: Arc::clone(self) }) .ok_or(WalletError::NullPointer) } } - - fn load_library(lib_path: Option<&str>) -> WalletResult<Library> { - if let Some(path) = lib_path { - unsafe { Library::new(path).map_err(|e| WalletError::LibraryLoadError(e.to_string())) } - } else { - let exe_path = std::env::current_exe() - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; - let exe_dir = exe_path.parent().ok_or_else(|| { - WalletError::LibraryLoadError("Failed to get executable directory".to_string()) - })?; - - let candidates = Self::get_library_candidates(exe_dir); - - candidates - .into_iter() - .find_map(|path| unsafe { Library::new(&path).ok() }) - .ok_or_else(|| { - WalletError::LibraryLoadError(format!( - "Failed to load {} from standard paths", - LIB_NAME - )) - }) - } - } - - fn get_library_candidates(exe_dir: &std::path::Path) -> Vec<PathBuf> { - let mut candidates = Vec::new(); - - // Candidate 1: ../../../../release/ relative to the executable. - if let Some(lib_dir) = exe_dir.ancestors().nth(4) { - candidates.push(lib_dir.join("release").join(LIB_NAME)); - } - - // Candidate 2: ../../lib/ relative to the executable. - if let Some(lib_dir) = exe_dir.ancestors().nth(2) { - candidates.push(lib_dir.join("lib").join(LIB_NAME)); - } - - // Candidate 3: Same directory as the executable. - candidates.push(exe_dir.join(LIB_NAME)); - // TODO: This should probably be the first candidate for binary - // distribution purposes; it will likely be the first place the library - // will be found in a binary distribution. - - // Candidate 4: Standard library paths. - candidates.push(PathBuf::from(LIB_NAME)); - - candidates - } } pub struct Wallet { @@ -156,19 +69,13 @@ pub struct Wallet { } impl Wallet { + /// Retrieves the wallet's seed with an optional offset. pub fn get_seed(&self, seed_offset: &str) -> WalletResult<String> { let c_seed_offset = CString::new(seed_offset) .map_err(|_| WalletError::FfiError("Invalid seed_offset".to_string()))?; unsafe { - let func: Symbol<unsafe extern "C" fn(*mut c_void, *const c_char) -> *const c_char> = - self.manager - .library - .get(b"MONERO_Wallet_seed\0") - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; - - let seed_ptr = func(self.ptr.as_ptr(), c_seed_offset.as_ptr()); - + let seed_ptr = bindings::MONERO_Wallet_seed(self.ptr.as_ptr(), c_seed_offset.as_ptr()); if seed_ptr.is_null() { Err(self.get_last_error()) } else { @@ -184,15 +91,10 @@ impl Wallet { } } + /// Retrieves the wallet's address for the given account and address index. pub fn get_address(&self, account_index: u64, address_index: u64) -> WalletResult<String> { unsafe { - let func: Symbol<unsafe extern "C" fn(*mut c_void, u64, u64) -> *const c_char> = - self.manager - .library - .get(b"MONERO_Wallet_address\0") - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; - let address_ptr = func(self.ptr.as_ptr(), account_index, address_index); - + let address_ptr = bindings::MONERO_Wallet_address(self.ptr.as_ptr(), account_index, address_index); if address_ptr.is_null() { Err(self.get_last_error()) } else { @@ -204,32 +106,19 @@ impl Wallet { } } + /// Checks if the wallet is deterministic. pub fn is_deterministic(&self) -> WalletResult<bool> { unsafe { - let func: Symbol<unsafe extern "C" fn(*mut c_void) -> bool> = self - .manager - .library - .get(b"MONERO_Wallet_isDeterministic\0") - .map_err(|e| WalletError::LibraryLoadError(e.to_string()))?; - Ok(func(self.ptr.as_ptr())) + let result = bindings::MONERO_Wallet_isDeterministic(self.ptr.as_ptr()); + Ok(result) } } - fn get_last_error(&self) -> WalletError { + /// Retrieves the last error from the wallet. + pub fn get_last_error(&self) -> WalletError { unsafe { - let error_func: Symbol<unsafe extern "C" fn(*mut c_void) -> *const c_char> = self - .manager - .library - .get(b"MONERO_Wallet_errorString\0") - .expect("Failed to load MONERO_Wallet_errorString"); - let status_func: Symbol<unsafe extern "C" fn(*mut c_void) -> c_int> = self - .manager - .library - .get(b"MONERO_Wallet_status\0") - .expect("Failed to load MONERO_Wallet_status"); - - let error_ptr = error_func(self.ptr.as_ptr()); - let status = status_func(self.ptr.as_ptr()); + let error_ptr = bindings::MONERO_Wallet_errorString(self.ptr.as_ptr()); + let status = bindings::MONERO_Wallet_status(self.ptr.as_ptr()); let error_msg = if error_ptr.is_null() { "Unknown error".to_string() @@ -247,14 +136,11 @@ impl Wallet { impl Drop for Wallet { fn drop(&mut self) { unsafe { - let func: Symbol< - unsafe extern "C" fn(*mut c_void, *mut c_void, bool) -> bool, - > = self - .manager - .library - .get(b"MONERO_WalletManager_closeWallet\0") - .expect("Failed to load MONERO_WalletManager_closeWallet"); - func(self.manager.ptr.as_ptr(), self.ptr.as_ptr(), false); + bindings::MONERO_WalletManager_closeWallet( + self.manager.ptr.as_ptr(), + self.ptr.as_ptr(), + false, // Don't save the wallet by default. + ); } } } |
