diff --git a/bindings/ergo-lib-c-core/src/ext_secret_key.rs b/bindings/ergo-lib-c-core/src/ext_secret_key.rs index eeb431d15..7fadb5a9f 100644 --- a/bindings/ergo-lib-c-core/src/ext_secret_key.rs +++ b/bindings/ergo-lib-c-core/src/ext_secret_key.rs @@ -2,37 +2,41 @@ use std::convert::TryInto; -use crate::util::const_ptr_as_ref; -use crate::{util::mut_ptr_as_mut, Error}; use derive_more::{From, Into}; -use ergo_lib::wallet::derivation_path::{ChildIndex, DerivationPath}; + +use ergo_lib::wallet::derivation_path::ChildIndex; use ergo_lib::wallet::ext_secret_key::{ ChainCode, ExtSecretKey as InnerExtSecretKey, SecretKeyBytes, }; use ergo_lib::wallet::mnemonic::MnemonicSeed; use ergo_lib::ArrLength; +use crate::derivation_path::{ConstDerivationPathPtr, DerivationPath, DerivationPathPtr}; +use crate::ext_pub_key::{ExtPubKey, ExtPubKeyPtr}; +use crate::secret_key::{SecretKey, SecretKeyPtr}; +use crate::util::const_ptr_as_ref; +use crate::{util::mut_ptr_as_mut, Error}; + #[derive(From, Into)] pub struct ExtSecretKey(InnerExtSecretKey); pub type ExtSecretKeyPtr = *mut ExtSecretKey; pub type ConstExtSecretKeyPtr = *const ExtSecretKey; /// Create ExtSecretKey from secret key bytes, chain code and derivation path -/// Derivation path should be a string in the form of: m/44/429/acc'/0/addr pub unsafe fn ext_secret_key_new( secret_key_bytes: *const u8, chain_code: *const u8, - derivation_path: &str, + derivation_path_ptr: ConstDerivationPathPtr, ext_secret_key_out: *mut ExtSecretKeyPtr, ) -> Result<(), Error> { let ext_secret_key_out = mut_ptr_as_mut(ext_secret_key_out, "ext_secret_key_out")?; - let derivation_path: DerivationPath = derivation_path.parse().map_err(Error::misc)?; + let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?; let secret_key_bytes = std::slice::from_raw_parts(secret_key_bytes, SecretKeyBytes::LEN); let chain_code = std::slice::from_raw_parts(chain_code, ChainCode::LEN); let key = InnerExtSecretKey::new( secret_key_bytes.try_into().map_err(Error::misc)?, chain_code.try_into().map_err(Error::misc)?, - derivation_path, + derivation_path.0.clone(), ) .map_err(Error::misc)?; *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey(key))); @@ -67,3 +71,55 @@ pub unsafe fn ext_secret_key_child( *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey(key))); Ok(()) } + +/// Get derivation path for extended secret key +pub unsafe fn ext_secret_key_path( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + derivation_path_out: *mut DerivationPathPtr, +) -> Result<(), Error> { + let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?; + let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?; + *derivation_path_out = Box::into_raw(Box::new(DerivationPath(ext_secret_key.0.path()))); + Ok(()) +} + +/// Get secret key for extended secret key +pub unsafe fn ext_secret_key_get_secret_key( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + secret_key_out: *mut SecretKeyPtr, +) -> Result<(), Error> { + let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?; + let secret_key_out = mut_ptr_as_mut(secret_key_out, "secret_key_out")?; + *secret_key_out = Box::into_raw(Box::new(SecretKey(ext_secret_key.0.secret_key()))); + Ok(()) +} + +/// The extended public key associated with this secret key +pub unsafe fn ext_secret_key_public_key( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + ext_pub_key_out: *mut ExtPubKeyPtr, +) -> Result<(), Error> { + let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?; + let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?; + let ext_pub_key = ExtPubKey(ext_secret_key.0.public_key().map_err(Error::misc)?); + *ext_pub_key_out = Box::into_raw(Box::new(ext_pub_key)); + Ok(()) +} + +/// Derive a new extended secret key from the derivation path +pub unsafe fn ext_secret_key_derive( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + derivation_path_ptr: ConstDerivationPathPtr, + ext_secret_key_out: *mut ExtSecretKeyPtr, +) -> Result<(), Error> { + let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?; + let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?; + let ext_secret_key_out = mut_ptr_as_mut(ext_secret_key_out, "ext_secret_key_out")?; + *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey( + ext_secret_key + .0 + .derive(derivation_path.0.clone()) + .map_err(Error::misc)?, + ))); + Ok(()) +} diff --git a/bindings/ergo-lib-c/src/ext_secret_key.rs b/bindings/ergo-lib-c/src/ext_secret_key.rs index a79833774..43b2edf22 100644 --- a/bindings/ergo-lib-c/src/ext_secret_key.rs +++ b/bindings/ergo-lib-c/src/ext_secret_key.rs @@ -2,7 +2,14 @@ use std::{ffi::CStr, os::raw::c_char}; +use ergo_lib_c_core::derivation_path::{ConstDerivationPathPtr, DerivationPathPtr}; +use ergo_lib_c_core::ext_secret_key::{ + ext_secret_key_derive, ext_secret_key_get_secret_key, ext_secret_key_path, + ext_secret_key_public_key, +}; +use ergo_lib_c_core::secret_key::SecretKeyPtr; use ergo_lib_c_core::{ + ext_pub_key::ExtPubKeyPtr, ext_secret_key::{ ext_secret_key_child, ext_secret_key_derive_master, ext_secret_key_new, ConstExtSecretKeyPtr, ExtSecretKeyPtr, @@ -13,19 +20,17 @@ use ergo_lib_c_core::{ use crate::{delete_ptr, ErrorPtr}; /// Create ExtSecretKey from secret key bytes, chain code and derivation path -/// Derivation path should be a string in the form of: m/44/429/acc'/0/addr #[no_mangle] pub unsafe extern "C" fn ergo_lib_ext_secret_key_new( secret_key_bytes_ptr: *const u8, chain_code_ptr: *const u8, - derivation_path_str: *const c_char, + derivation_path_ptr: ConstDerivationPathPtr, ext_secret_key_out: *mut ExtSecretKeyPtr, ) -> ErrorPtr { - let derivation_path = CStr::from_ptr(derivation_path_str).to_string_lossy(); let res = ext_secret_key_new( secret_key_bytes_ptr, chain_code_ptr, - &derivation_path, + derivation_path_ptr, ext_secret_key_out, ); Error::c_api_from(res) @@ -55,6 +60,47 @@ pub unsafe extern "C" fn ergo_lib_ext_secret_key_child( Error::c_api_from(res) } +/// Get derivation path for extended secret key +#[no_mangle] +pub unsafe extern "C" fn ergo_lib_ext_secret_key_path( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + derivation_path_out: *mut DerivationPathPtr, +) { + #[allow(clippy::unwrap_used)] + ext_secret_key_path(ext_secret_key_ptr, derivation_path_out).unwrap() +} + +/// Get secret key for extended secret key +#[no_mangle] +pub unsafe extern "C" fn ergo_lib_ext_secret_key_get_secret_key( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + secret_key_out: *mut SecretKeyPtr, +) { + #[allow(clippy::unwrap_used)] + ext_secret_key_get_secret_key(ext_secret_key_ptr, secret_key_out).unwrap() +} + +/// The extended public key associated with this secret key +#[no_mangle] +pub unsafe extern "C" fn ergo_lib_ext_secret_key_public_key( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + ext_pub_key_out: *mut ExtPubKeyPtr, +) { + #[allow(clippy::unwrap_used)] + ext_secret_key_public_key(ext_secret_key_ptr, ext_pub_key_out).unwrap() +} + +/// Derive a new extended secret key from the derivation path +#[no_mangle] +pub unsafe extern "C" fn ergo_lib_ext_secret_key_derive( + ext_secret_key_ptr: ConstExtSecretKeyPtr, + derivation_path_ptr: ConstDerivationPathPtr, + ext_secret_key_out: *mut ExtSecretKeyPtr, +) -> ErrorPtr { + let res = ext_secret_key_derive(ext_secret_key_ptr, derivation_path_ptr, ext_secret_key_out); + Error::c_api_from(res) +} + /// Drop `ExtSecretKey` #[no_mangle] pub extern "C" fn ergo_lib_ext_secret_key_delete(ptr: ExtSecretKeyPtr) { diff --git a/bindings/ergo-lib-ios/Sources/ErgoLib/ExtSecretKey.swift b/bindings/ergo-lib-ios/Sources/ErgoLib/ExtSecretKey.swift index 4e9f1fe08..c30d13b56 100644 --- a/bindings/ergo-lib-ios/Sources/ErgoLib/ExtSecretKey.swift +++ b/bindings/ergo-lib-ios/Sources/ErgoLib/ExtSecretKey.swift @@ -5,12 +5,9 @@ class ExtSecretKey { internal var pointer: ExtSecretKeyPtr /// Create ExtSecretKey from secret key bytes, chain code and derivation path - /// Derivation path should be a string in the form of: m/44/429/acc'/0/addr - init(secretKeyBytes: [UInt8], chainCodeBytes: [UInt8], derivationPathStr: String) throws { + init(secretKeyBytes: [UInt8], chainCodeBytes: [UInt8], derivationPath: DerivationPath) throws { var ptr: ExtSecretKeyPtr? - let error = derivationPathStr.withCString { cs in - ergo_lib_ext_secret_key_new(secretKeyBytes, chainCodeBytes, cs, &ptr) - } + let error = ergo_lib_ext_secret_key_new(secretKeyBytes, chainCodeBytes, derivationPath, &ptr) try checkError(error) self.pointer = ptr! }