Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i741 expose missing types and functions #742

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions bindings/ergo-lib-c-core/src/derivation_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//! Derivation Path functionality

use crate::util::const_ptr_as_ref;
use crate::{util::mut_ptr_as_mut, Error};
use derive_more::{From, Into};
use ergo_lib::wallet;
use ergo_lib::wallet::derivation_path::{
ChildIndexError, ChildIndexHardened, ChildIndexNormal, DerivationPath as InnerDerivationPath,
};
use std::str::FromStr;

#[derive(From, Into)]
pub struct DerivationPath(pub InnerDerivationPath);
pub type DerivationPathPtr = *mut DerivationPath;
pub type ConstDerivationPathPtr = *const DerivationPath;

/// Create DerivationPath from account index and address indices
pub unsafe fn derivation_path_new(
account: u32,
address_indices: &[u32],
derivation_path_out: *mut DerivationPathPtr,
) -> Result<(), Error> {
let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
let acc = ChildIndexHardened::from_31_bit(account)?;
let address_indices = address_indices
.iter()
.map(|i| ChildIndexNormal::normal(*i))
.collect::<Result<Vec<ChildIndexNormal>, ChildIndexError>>()
.map_err(Error::misc)?;
let derivation_path = DerivationPath(InnerDerivationPath::new(acc, address_indices));
*derivation_path_out = Box::into_raw(Box::new(derivation_path));
Ok(())
}

/// Create derivation path from string
/// String should be in the form of: m/44/429/acc'/0/addr
pub unsafe fn derivation_path_from_str(
derivation_path_str: &str,
derivation_path_out: *mut DerivationPathPtr,
) -> Result<(), Error> {
let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
let derivation_path = wallet::derivation_path::DerivationPath::from_str(derivation_path_str)
.map_err(Error::misc)?;
*derivation_path_out = Box::into_raw(Box::new(DerivationPath(derivation_path)));
Ok(())
}

/// Get derivation path as string in the m/44/429/acc'/0/addr format
pub unsafe fn derivation_path_to_str(
derivation_path_ptr: ConstDerivationPathPtr,
) -> Result<String, Error> {
let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
let s = derivation_path.0.to_string();
Ok(s)
}

/// Returns the length of the derivation path
pub unsafe fn derivation_path_depth(
derivation_path_ptr: ConstDerivationPathPtr,
) -> Result<usize, Error> {
let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
Ok(derivation_path.0.depth())
}

/// Returns a new derivation path with the last element of the derivation path being increased, e.g. m/1/2 -> m/1/3
pub unsafe fn derivation_path_next(
derivation_path_ptr: ConstDerivationPathPtr,
derivation_path_out: *mut DerivationPathPtr,
) -> Result<(), Error> {
let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
*derivation_path_out = Box::into_raw(Box::new(DerivationPath(
derivation_path.0.next().map_err(Error::misc)?,
)));
Ok(())
}
89 changes: 89 additions & 0 deletions bindings/ergo-lib-c-core/src/ext_pub_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//! Extended Public Key functionality

use derive_more::{From, Into};

use ergo_lib::ergotree_ir::chain::address::Address as InnerAddress;
use ergo_lib::wallet::derivation_path::ChildIndexNormal;
use ergo_lib::wallet::ext_pub_key::{ExtPubKey as InnerExtPubKey, PubKeyBytes};
use ergo_lib::ArrLength;

use crate::address::{Address, AddressPtr};
use crate::derivation_path::ConstDerivationPathPtr;
use crate::util::{const_ptr_as_ref, mut_ptr_as_mut};
use crate::Error;

#[derive(From, Into)]
pub struct ExtPubKey(pub InnerExtPubKey);
pub type ExtPubKeyPtr = *mut ExtPubKey;
pub type ConstExtPubKeyPtr = *const ExtPubKey;

/// Create ExtPubKey from public key bytes, chain code and derivation path
/// public_key_bytes needs to be the length of PubKeyBytes::LEN (33 bytes)
/// chain_code needs to be the length of ChainCode::LEN (32 bytes)
pub unsafe fn ext_pub_key_new(
public_key_bytes: *const u8,
chain_code: *const u8,
derivation_path_ptr: ConstDerivationPathPtr,
ext_pub_key_out: *mut ExtPubKeyPtr,
) -> Result<(), Error> {
let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
let secret_key_bytes = std::slice::from_raw_parts(public_key_bytes, PubKeyBytes::LEN);
let chain_code =
std::slice::from_raw_parts(chain_code, ergo_lib::wallet::ext_pub_key::ChainCode::LEN);
let key = InnerExtPubKey::new(
secret_key_bytes.try_into().map_err(Error::misc)?,
chain_code.try_into().map_err(Error::misc)?,
derivation_path.0.clone(),
)
.map_err(Error::misc)?;
*ext_pub_key_out = Box::into_raw(Box::new(ExtPubKey(key)));
Ok(())
}

/// Derive a new extended public key from the provided index
/// The index is in the form of soft or hardened indices
/// For example: 4 or 4' respectively
pub unsafe fn ext_pub_key_child(
derive_from_key_ptr: ConstExtPubKeyPtr,
child_index: u32,
ext_pub_key_out: *mut ExtPubKeyPtr,
) -> Result<(), Error> {
let ext_pub_key = const_ptr_as_ref(derive_from_key_ptr, "derive_from_key_ptr")?;
let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
let index = ChildIndexNormal::normal(child_index).map_err(Error::misc)?;
let key = ext_pub_key.0.child(index);
*ext_pub_key_out = Box::into_raw(Box::new(ExtPubKey(key)));
Ok(())
}

/// Derive a new extended public key from the derivation path
pub unsafe fn ext_pub_key_derive(
ext_pub_key_ptr: ConstExtPubKeyPtr,
derivation_path_ptr: ConstDerivationPathPtr,
ext_pub_key_out: *mut ExtPubKeyPtr,
) -> Result<(), Error> {
let ext_pub_key_ptr = const_ptr_as_ref(ext_pub_key_ptr, "ext_pub_key_ptr")?;
let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
*ext_pub_key_out = Box::into_raw(Box::new(ExtPubKey(
ext_pub_key_ptr
.0
.derive(derivation_path.0.clone())
.map_err(Error::misc)?,
)));
Ok(())
}

/// Get address for extended public key
pub unsafe fn ext_pub_key_address(
ext_pub_key_ptr: ConstExtPubKeyPtr,
address_out: *mut AddressPtr,
) -> Result<(), Error> {
let ext_pub_key_ptr = const_ptr_as_ref(ext_pub_key_ptr, "ext_pub_key_ptr")?;
let address_out = mut_ptr_as_mut(address_out, "address_out")?;
let ext_pub_key: InnerExtPubKey = ext_pub_key_ptr.0.clone();
let address = InnerAddress::from(ext_pub_key);
*address_out = Box::into_raw(Box::new(Address(address)));
Ok(())
}
72 changes: 65 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,43 @@

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
/// secret_key_bytes needs to be the length of SecretKeyBytes::LEN (32 bytes)
/// chain_code needs to be the length of ChainCode::LEN (32 bytes)
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 +73,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(())
}
3 changes: 3 additions & 0 deletions bindings/ergo-lib-c-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ pub mod tx_builder;
pub mod util;
pub mod wallet;
pub use crate::error::*;
pub mod derivation_path;
mod error;
pub mod ext_pub_key;
pub mod mnemonic;
#[cfg(feature = "rest")]
pub mod rest;
14 changes: 14 additions & 0 deletions bindings/ergo-lib-c-core/src/mnemonic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::Error;
use ergo_lib::wallet::mnemonic::Mnemonic as InnerMnemonic;

/// Convert a mnemonic phrase into a mnemonic seed
/// mnemonic_pass is optional and is used to salt the seed
pub unsafe fn mnemonic_to_seed(
mnemonic_phrase: &str,
mnemonic_pass: &str,
output: *mut u8,
) -> Result<(), Error> {
let src: Vec<u8> = InnerMnemonic::to_seed(mnemonic_phrase, mnemonic_pass).into();
std::ptr::copy_nonoverlapping(src.as_ptr(), output, src.len());
Ok(())
}
73 changes: 73 additions & 0 deletions bindings/ergo-lib-c/src/derivation_path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Derivation Path functionality

use crate::{delete_ptr, ErrorPtr};
use ergo_lib_c_core::derivation_path::{
derivation_path_depth, derivation_path_from_str, derivation_path_new, derivation_path_next,
derivation_path_to_str, ConstDerivationPathPtr, DerivationPathPtr,
};
use ergo_lib_c_core::Error;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;

/// Create DerivationPath from account index and address indices
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_derivation_path_new(
account: u32,
address_indices: *const u32,
len: usize,
derivation_path_out: *mut DerivationPathPtr,
) -> ErrorPtr {
let address_indices = std::slice::from_raw_parts(address_indices, len);
let res = derivation_path_new(account, address_indices, derivation_path_out);
Error::c_api_from(res)
}

/// Create derivation path from string
/// String should be in the form of: m/44/429/acc'/0/addr
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_derivation_path_from_str(
derivation_path_str: *const c_char,
derivation_path_out: *mut DerivationPathPtr,
) -> ErrorPtr {
let derivation_path_str = CStr::from_ptr(derivation_path_str).to_string_lossy();
let res = derivation_path_from_str(&derivation_path_str, derivation_path_out);
Error::c_api_from(res)
}

/// Get derivation path as string in the m/44/429/acc'/0/addr format
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_derivation_path_to_str(
derivation_path_ptr: ConstDerivationPathPtr,
_derivation_path_str: *mut *const c_char,
) {
#[allow(clippy::unwrap_used)]
{
let s = derivation_path_to_str(derivation_path_ptr).unwrap();
*_derivation_path_str = CString::new(s).unwrap().into_raw();
}
}

/// Returns the length of the derivation path
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_derivation_path_depth(
derivation_path_ptr: ConstDerivationPathPtr,
) -> usize {
#[allow(clippy::unwrap_used)]
derivation_path_depth(derivation_path_ptr).unwrap()
}

/// Returns a new derivation path with the last element of the derivation path being increased, e.g. m/1/2 -> m/1/3
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_derivation_path_next(
derivation_path_ptr: ConstDerivationPathPtr,
derivation_path_out: *mut DerivationPathPtr,
) -> ErrorPtr {
let res = derivation_path_next(derivation_path_ptr, derivation_path_out);
Error::c_api_from(res)
}

/// Drop `DerivationPath`
#[no_mangle]
pub extern "C" fn ergo_lib_derivation_path_delete(ptr: DerivationPathPtr) {
unsafe { delete_ptr(ptr) }
}
Loading
Loading