Skip to main content

ergo_lib_c_core/
ext_pub_key.rs

1//! Extended Public Key functionality
2
3use derive_more::{From, Into};
4
5use ergo_lib::ergotree_ir::chain::address::Address as InnerAddress;
6use ergo_lib::wallet::derivation_path::ChildIndexNormal;
7use ergo_lib::wallet::ext_pub_key::{ExtPubKey as InnerExtPubKey, PubKeyBytes};
8use ergo_lib::ArrLength;
9
10use crate::address::{Address, AddressPtr};
11use crate::derivation_path::ConstDerivationPathPtr;
12use crate::util::{const_ptr_as_ref, mut_ptr_as_mut};
13use crate::Error;
14
15#[derive(From, Into)]
16pub struct ExtPubKey(pub InnerExtPubKey);
17pub type ExtPubKeyPtr = *mut ExtPubKey;
18pub type ConstExtPubKeyPtr = *const ExtPubKey;
19
20/// Create ExtPubKey from public key bytes, chain code and derivation path
21/// public_key_bytes needs to be the length of PubKeyBytes::LEN (33 bytes)
22/// chain_code needs to be the length of ChainCode::LEN (32 bytes)
23pub unsafe fn ext_pub_key_new(
24    public_key_bytes: *const u8,
25    chain_code: *const u8,
26    derivation_path_ptr: ConstDerivationPathPtr,
27    ext_pub_key_out: *mut ExtPubKeyPtr,
28) -> Result<(), Error> {
29    let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
30    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
31    let secret_key_bytes = std::slice::from_raw_parts(public_key_bytes, PubKeyBytes::LEN);
32    let chain_code =
33        std::slice::from_raw_parts(chain_code, ergo_lib::wallet::ext_pub_key::ChainCode::LEN);
34    let key = InnerExtPubKey::new(
35        secret_key_bytes.try_into().map_err(Error::misc)?,
36        chain_code.try_into().map_err(Error::misc)?,
37        derivation_path.0.clone(),
38    )
39    .map_err(Error::misc)?;
40    *ext_pub_key_out = Box::into_raw(Box::new(ExtPubKey(key)));
41    Ok(())
42}
43
44/// Derive a new extended public key from the provided index
45/// The index is in the form of soft or hardened indices
46/// For example: 4 or 4' respectively
47pub unsafe fn ext_pub_key_child(
48    derive_from_key_ptr: ConstExtPubKeyPtr,
49    child_index: u32,
50    ext_pub_key_out: *mut ExtPubKeyPtr,
51) -> Result<(), Error> {
52    let ext_pub_key = const_ptr_as_ref(derive_from_key_ptr, "derive_from_key_ptr")?;
53    let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
54    let index = ChildIndexNormal::normal(child_index).map_err(Error::misc)?;
55    let key = ext_pub_key.0.child(index);
56    *ext_pub_key_out = Box::into_raw(Box::new(ExtPubKey(key)));
57    Ok(())
58}
59
60/// Derive a new extended public key from the derivation path
61pub unsafe fn ext_pub_key_derive(
62    ext_pub_key_ptr: ConstExtPubKeyPtr,
63    derivation_path_ptr: ConstDerivationPathPtr,
64    ext_pub_key_out: *mut ExtPubKeyPtr,
65) -> Result<(), Error> {
66    let ext_pub_key_ptr = const_ptr_as_ref(ext_pub_key_ptr, "ext_pub_key_ptr")?;
67    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
68    let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
69    *ext_pub_key_out = Box::into_raw(Box::new(ExtPubKey(
70        ext_pub_key_ptr
71            .0
72            .derive(derivation_path.0.clone())
73            .map_err(Error::misc)?,
74    )));
75    Ok(())
76}
77
78/// Get address for extended public key
79pub unsafe fn ext_pub_key_address(
80    ext_pub_key_ptr: ConstExtPubKeyPtr,
81    address_out: *mut AddressPtr,
82) -> Result<(), Error> {
83    let ext_pub_key_ptr = const_ptr_as_ref(ext_pub_key_ptr, "ext_pub_key_ptr")?;
84    let address_out = mut_ptr_as_mut(address_out, "address_out")?;
85    let ext_pub_key: InnerExtPubKey = ext_pub_key_ptr.0.clone();
86    let address = InnerAddress::from(ext_pub_key);
87    *address_out = Box::into_raw(Box::new(Address(address)));
88    Ok(())
89}