Skip to content

Commit

Permalink
implement ExtPubKey in c-bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
Alesfatalis committed May 3, 2024
1 parent e4a9b53 commit 5693da5
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 0 deletions.
87 changes: 87 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,87 @@
//! 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
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(())
}
1 change: 1 addition & 0 deletions bindings/ergo-lib-c-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@ pub mod wallet;
pub use crate::error::*;
pub mod derivation_path;
mod error;
pub mod ext_pub_key;
#[cfg(feature = "rest")]
pub mod rest;
67 changes: 67 additions & 0 deletions bindings/ergo-lib-c/src/ext_pub_key.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Extended Public Key functionality
use crate::{delete_ptr, ErrorPtr};
use ergo_lib_c_core::address::AddressPtr;
use ergo_lib_c_core::derivation_path::ConstDerivationPathPtr;
use ergo_lib_c_core::ext_pub_key::{
ext_pub_key_address, ext_pub_key_child, ext_pub_key_derive, ext_pub_key_new, ConstExtPubKeyPtr,
ExtPubKeyPtr,
};
use ergo_lib_c_core::Error;

/// Create ExtPubKey from public key bytes, chain code and derivation path
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_ext_pub_key_new(
public_key_bytes: *const u8,
chain_code_ptr: *const u8,
derivation_path_ptr: ConstDerivationPathPtr,
ext_pub_key_out: *mut ExtPubKeyPtr,
) -> ErrorPtr {
let res = ext_pub_key_new(
public_key_bytes,
chain_code_ptr,
derivation_path_ptr,
ext_pub_key_out,
);
Error::c_api_from(res)
}

/// 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
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_ext_pub_key_child(
derive_from_key_ptr: ConstExtPubKeyPtr,
child_index: u32,
ext_pub_key_out: *mut ExtPubKeyPtr,
) -> ErrorPtr {
let res = ext_pub_key_child(derive_from_key_ptr, child_index, ext_pub_key_out);
Error::c_api_from(res)
}

/// Derive a new extended public key from the derivation path
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_ext_pub_key_derive(
ext_pub_key_ptr: ConstExtPubKeyPtr,
derivation_path_ptr: ConstDerivationPathPtr,
ext_pub_key_out: *mut ExtPubKeyPtr,
) -> ErrorPtr {
let res = ext_pub_key_derive(ext_pub_key_ptr, derivation_path_ptr, ext_pub_key_out);
Error::c_api_from(res)
}

/// Get address for extended public key
#[no_mangle]
pub unsafe extern "C" fn ergo_lib_ext_pub_key_address(
ext_pub_key_ptr: ConstExtPubKeyPtr,
address_out: *mut AddressPtr,
) {
#[allow(clippy::unwrap_used)]
ext_pub_key_address(ext_pub_key_ptr, address_out).unwrap()
}

/// Drop `ExtPubKey`
#[no_mangle]
pub extern "C" fn ergo_lib_ext_pub_key_delete(ptr: ExtPubKeyPtr) {
unsafe { delete_ptr(ptr) }
}
1 change: 1 addition & 0 deletions bindings/ergo-lib-c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mod reduced;
mod rest;

mod derivation_path;
mod ext_pub_key;
mod secret_key;
mod token;
mod transaction;
Expand Down

0 comments on commit 5693da5

Please sign in to comment.