Skip to content

Commit

Permalink
add missing functions for ExtSecretKey in c-bindings
Browse files Browse the repository at this point in the history
- change function ext_secret_key_new to accept DerivationPath as parameter
  • Loading branch information
Alesfatalis committed May 3, 2024
1 parent 5693da5 commit b919656
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 16 deletions.
70 changes: 63 additions & 7 deletions bindings/ergo-lib-c-core/src/ext_secret_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand Down Expand Up @@ -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(())
}
54 changes: 50 additions & 4 deletions bindings/ergo-lib-c/src/ext_secret_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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) {
Expand Down
7 changes: 2 additions & 5 deletions bindings/ergo-lib-ios/Sources/ErgoLib/ExtSecretKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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!
}
Expand Down

0 comments on commit b919656

Please sign in to comment.