Skip to main content

ergo_lib_c_core/
ext_secret_key.rs

1//! Extended Secret Key functionality
2
3use std::convert::TryInto;
4
5use derive_more::{From, Into};
6
7use ergo_lib::wallet::derivation_path::ChildIndex;
8use ergo_lib::wallet::ext_secret_key::{
9    ChainCode, ExtSecretKey as InnerExtSecretKey, SecretKeyBytes,
10};
11use ergo_lib::wallet::mnemonic::MnemonicSeed;
12use ergo_lib::ArrLength;
13
14use crate::derivation_path::{ConstDerivationPathPtr, DerivationPath, DerivationPathPtr};
15use crate::ext_pub_key::{ExtPubKey, ExtPubKeyPtr};
16use crate::secret_key::{SecretKey, SecretKeyPtr};
17use crate::util::const_ptr_as_ref;
18use crate::{util::mut_ptr_as_mut, Error};
19
20#[derive(From, Into)]
21pub struct ExtSecretKey(InnerExtSecretKey);
22pub type ExtSecretKeyPtr = *mut ExtSecretKey;
23pub type ConstExtSecretKeyPtr = *const ExtSecretKey;
24
25/// Create ExtSecretKey from secret key bytes, chain code and derivation path
26/// secret_key_bytes needs to be the length of SecretKeyBytes::LEN (32 bytes)
27/// chain_code needs to be the length of ChainCode::LEN (32 bytes)
28pub unsafe fn ext_secret_key_new(
29    secret_key_bytes: *const u8,
30    chain_code: *const u8,
31    derivation_path_ptr: ConstDerivationPathPtr,
32    ext_secret_key_out: *mut ExtSecretKeyPtr,
33) -> Result<(), Error> {
34    let ext_secret_key_out = mut_ptr_as_mut(ext_secret_key_out, "ext_secret_key_out")?;
35    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
36    let secret_key_bytes = std::slice::from_raw_parts(secret_key_bytes, SecretKeyBytes::LEN);
37    let chain_code = std::slice::from_raw_parts(chain_code, ChainCode::LEN);
38    let key = InnerExtSecretKey::new(
39        secret_key_bytes.try_into().map_err(Error::misc)?,
40        chain_code.try_into().map_err(Error::misc)?,
41        derivation_path.0.clone(),
42    )
43    .map_err(Error::misc)?;
44    *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey(key)));
45    Ok(())
46}
47
48/// Derive root extended secret key
49pub unsafe fn ext_secret_key_derive_master(
50    seed: *const u8,
51    ext_secret_key_out: *mut ExtSecretKeyPtr,
52) -> Result<(), Error> {
53    let ext_secret_key_out = mut_ptr_as_mut(ext_secret_key_out, "ext_secret_key_out")?;
54    let seed = std::slice::from_raw_parts(seed, MnemonicSeed::LEN);
55    let key = InnerExtSecretKey::derive_master(seed.try_into().map_err(Error::misc)?)
56        .map_err(Error::misc)?;
57    *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey(key)));
58    Ok(())
59}
60
61/// Derive a new extended secret key from the provided index
62/// The index is in the form of soft or hardened indices
63/// For example: 4 or 4' respectively
64pub unsafe fn ext_secret_key_child(
65    derive_from_key_ptr: ConstExtSecretKeyPtr,
66    child_index: &str,
67    ext_secret_key_out: *mut ExtSecretKeyPtr,
68) -> Result<(), Error> {
69    let ext_secret_key = const_ptr_as_ref(derive_from_key_ptr, "derive_from_key_ptr")?;
70    let ext_secret_key_out = mut_ptr_as_mut(ext_secret_key_out, "ext_secret_key_out")?;
71    let index = child_index.parse::<ChildIndex>().map_err(Error::misc)?;
72    let key = ext_secret_key.0.child(index).map_err(Error::misc)?;
73    *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey(key)));
74    Ok(())
75}
76
77/// Get derivation path for extended secret key
78pub unsafe fn ext_secret_key_path(
79    ext_secret_key_ptr: ConstExtSecretKeyPtr,
80    derivation_path_out: *mut DerivationPathPtr,
81) -> Result<(), Error> {
82    let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?;
83    let derivation_path_out = mut_ptr_as_mut(derivation_path_out, "derivation_path_out")?;
84    *derivation_path_out = Box::into_raw(Box::new(DerivationPath(ext_secret_key.0.path())));
85    Ok(())
86}
87
88/// Get secret key for extended secret key
89pub unsafe fn ext_secret_key_get_secret_key(
90    ext_secret_key_ptr: ConstExtSecretKeyPtr,
91    secret_key_out: *mut SecretKeyPtr,
92) -> Result<(), Error> {
93    let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?;
94    let secret_key_out = mut_ptr_as_mut(secret_key_out, "secret_key_out")?;
95    *secret_key_out = Box::into_raw(Box::new(SecretKey(ext_secret_key.0.secret_key())));
96    Ok(())
97}
98
99/// The extended public key associated with this secret key
100pub unsafe fn ext_secret_key_public_key(
101    ext_secret_key_ptr: ConstExtSecretKeyPtr,
102    ext_pub_key_out: *mut ExtPubKeyPtr,
103) -> Result<(), Error> {
104    let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?;
105    let ext_pub_key_out = mut_ptr_as_mut(ext_pub_key_out, "ext_pub_key_out")?;
106    let ext_pub_key = ExtPubKey(ext_secret_key.0.public_key().map_err(Error::misc)?);
107    *ext_pub_key_out = Box::into_raw(Box::new(ext_pub_key));
108    Ok(())
109}
110
111/// Derive a new extended secret key from the derivation path
112pub unsafe fn ext_secret_key_derive(
113    ext_secret_key_ptr: ConstExtSecretKeyPtr,
114    derivation_path_ptr: ConstDerivationPathPtr,
115    ext_secret_key_out: *mut ExtSecretKeyPtr,
116) -> Result<(), Error> {
117    let ext_secret_key = const_ptr_as_ref(ext_secret_key_ptr, "ext_secret_key_ptr")?;
118    let derivation_path = const_ptr_as_ref(derivation_path_ptr, "derivation_path_ptr")?;
119    let ext_secret_key_out = mut_ptr_as_mut(ext_secret_key_out, "ext_secret_key_out")?;
120    *ext_secret_key_out = Box::into_raw(Box::new(ExtSecretKey(
121        ext_secret_key
122            .0
123            .derive(derivation_path.0.clone())
124            .map_err(Error::misc)?,
125    )));
126    Ok(())
127}