Skip to content

Commit

Permalink
feat: add descriptor key related error
Browse files Browse the repository at this point in the history
  • Loading branch information
reez committed Apr 26, 2024
1 parent e609b57 commit e1a9337
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 30 deletions.
19 changes: 13 additions & 6 deletions bdk-ffi/src/bdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ interface Bip32Error {
UnknownError(string e);
};

[Error]
interface DescriptorKeyError {
Parse(string e);
InvalidKeyType();
Bip32(string e);
};

[Error]
interface CalculateFeeError {
MissingTxOut(sequence<OutPoint> out_points);
Expand Down Expand Up @@ -369,13 +376,13 @@ interface DerivationPath {
interface DescriptorSecretKey {
constructor(Network network, [ByRef] Mnemonic mnemonic, string? password);

[Name=from_string, Throws=Alpha3Error]
[Name=from_string, Throws=DescriptorKeyError]
constructor(string secret_key);

[Throws=Alpha3Error]
[Throws=DescriptorKeyError]
DescriptorSecretKey derive([ByRef] DerivationPath path);

[Throws=Alpha3Error]
[Throws=DescriptorKeyError]
DescriptorSecretKey extend([ByRef] DerivationPath path);

DescriptorPublicKey as_public();
Expand All @@ -386,13 +393,13 @@ interface DescriptorSecretKey {
};

interface DescriptorPublicKey {
[Name=from_string, Throws=Alpha3Error]
[Name=from_string, Throws=DescriptorKeyError]
constructor(string public_key);

[Throws=Alpha3Error]
[Throws=DescriptorKeyError]
DescriptorPublicKey derive([ByRef] DerivationPath path);

[Throws=Alpha3Error]
[Throws=DescriptorKeyError]
DescriptorPublicKey extend([ByRef] DerivationPath path);

string as_string();
Expand Down
29 changes: 29 additions & 0 deletions bdk-ffi/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use bitcoin_internals::hex::display::DisplayHex;
use crate::error::bip32::Error as BdkBip32Error;
use bdk::bitcoin::address::ParseError;
use bdk::keys::bip39::Error as BdkBip39Error;
use bdk::miniscript::descriptor::DescriptorKeyParseError as BdkDescriptorKeyParseError;

use bdk::bitcoin::bip32;

Expand Down Expand Up @@ -133,6 +134,18 @@ pub enum CreateTxError {
MiniscriptPsbt { e: String },
}

#[derive(Debug, thiserror::Error)]
pub enum DescriptorKeyError {
#[error("error parsing descriptor key: {e}")]
Parse { e: String },

#[error("error invalid key type")]
InvalidKeyType,

#[error("error bip 32 related: {e}")]
Bip32 { e: String },
}

#[derive(Debug, thiserror::Error)]
pub enum CalculateFeeError {
#[error("missing transaction output: {out_points:?}")]
Expand Down Expand Up @@ -545,6 +558,22 @@ impl From<BdkSignerError> for SignerError {
}
}

impl From<BdkDescriptorKeyParseError> for DescriptorKeyError {
fn from(err: BdkDescriptorKeyParseError) -> DescriptorKeyError {
DescriptorKeyError::Parse {
e: format!("DescriptorKeyError error: {:?}", err),
}
}
}

impl From<bdk::bitcoin::bip32::Error> for DescriptorKeyError {
fn from(err: bdk::bitcoin::bip32::Error) -> DescriptorKeyError {
DescriptorKeyError::Bip32 {
e: format!("BIP32 derivation error: {:?}", err),
}
}
}

impl From<BdkPsbtParseError> for PsbtParseError {
fn from(error: BdkPsbtParseError) -> Self {
match error {
Expand Down
54 changes: 30 additions & 24 deletions bdk-ffi/src/keys.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::error::{Alpha3Error, Bip32Error, Bip39Error};
use crate::error::{Bip32Error, Bip39Error, DescriptorKeyError};

use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::key::Secp256k1;
Expand Down Expand Up @@ -86,22 +86,25 @@ impl DescriptorSecretKey {
}
}

pub(crate) fn from_string(private_key: String) -> Result<Self, Alpha3Error> {
pub(crate) fn from_string(private_key: String) -> Result<Self, DescriptorKeyError> {
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
.map_err(|_| Alpha3Error::Generic)?;
.map_err(DescriptorKeyError::from)?;
Ok(Self {
inner: descriptor_secret_key,
})
}

pub(crate) fn derive(&self, path: &DerivationPath) -> Result<Arc<Self>, Alpha3Error> {
pub(crate) fn derive(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
let secp = Secp256k1::new();
let descriptor_secret_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key {
BdkDescriptorSecretKey::Single(_) => Err(Alpha3Error::Generic),
BdkDescriptorSecretKey::Single(_) => Err(DescriptorKeyError::InvalidKeyType),
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
let derived_xprv = descriptor_x_key
.xkey
.derive_priv(&secp, &path)
.map_err(DescriptorKeyError::from)?;
let key_source = match descriptor_x_key.origin.clone() {
Some((fingerprint, origin_path)) => (fingerprint, origin_path.extend(path)),
None => (descriptor_x_key.xkey.fingerprint(&secp), path),
Expand All @@ -116,15 +119,15 @@ impl DescriptorSecretKey {
inner: derived_descriptor_secret_key,
}))
}
BdkDescriptorSecretKey::MultiXPrv(_) => Err(Alpha3Error::Generic),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(DescriptorKeyError::InvalidKeyType),
}
}

pub(crate) fn extend(&self, path: &DerivationPath) -> Result<Arc<Self>, Alpha3Error> {
pub(crate) fn extend(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
let descriptor_secret_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key {
BdkDescriptorSecretKey::Single(_) => Err(Alpha3Error::Generic),
BdkDescriptorSecretKey::Single(_) => Err(DescriptorKeyError::InvalidKeyType),
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
Expand All @@ -137,7 +140,7 @@ impl DescriptorSecretKey {
inner: extended_descriptor_secret_key,
}))
}
BdkDescriptorSecretKey::MultiXPrv(_) => Err(Alpha3Error::Generic),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(DescriptorKeyError::InvalidKeyType),
}
}

Expand Down Expand Up @@ -177,23 +180,26 @@ pub struct DescriptorPublicKey {
}

impl DescriptorPublicKey {
pub(crate) fn from_string(public_key: String) -> Result<Self, Alpha3Error> {
pub(crate) fn from_string(public_key: String) -> Result<Self, DescriptorKeyError> {
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
.map_err(|_| Alpha3Error::Generic)?;
.map_err(DescriptorKeyError::from)?;
Ok(Self {
inner: descriptor_public_key,
})
}

pub(crate) fn derive(&self, path: &DerivationPath) -> Result<Arc<Self>, Alpha3Error> {
pub(crate) fn derive(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
let secp = Secp256k1::new();
let descriptor_public_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();

match descriptor_public_key {
BdkDescriptorPublicKey::Single(_) => Err(Alpha3Error::Generic),
BdkDescriptorPublicKey::Single(_) => Err(DescriptorKeyError::InvalidKeyType),
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
let derived_xpub = descriptor_x_key
.xkey
.derive_pub(&secp, &path)
.map_err(DescriptorKeyError::from)?;
let key_source = match descriptor_x_key.origin.clone() {
Some((fingerprint, origin_path)) => (fingerprint, origin_path.extend(path)),
None => (descriptor_x_key.xkey.fingerprint(), path),
Expand All @@ -208,15 +214,15 @@ impl DescriptorPublicKey {
inner: derived_descriptor_public_key,
}))
}
BdkDescriptorPublicKey::MultiXPub(_) => Err(Alpha3Error::Generic),
BdkDescriptorPublicKey::MultiXPub(_) => Err(DescriptorKeyError::InvalidKeyType),
}
}

pub(crate) fn extend(&self, path: &DerivationPath) -> Result<Arc<Self>, Alpha3Error> {
pub(crate) fn extend(&self, path: &DerivationPath) -> Result<Arc<Self>, DescriptorKeyError> {
let descriptor_public_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key {
BdkDescriptorPublicKey::Single(_) => Err(Alpha3Error::Generic),
BdkDescriptorPublicKey::Single(_) => Err(DescriptorKeyError::InvalidKeyType),
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
Expand All @@ -229,7 +235,7 @@ impl DescriptorPublicKey {
inner: extended_descriptor_public_key,
}))
}
BdkDescriptorPublicKey::MultiXPub(_) => Err(Alpha3Error::Generic),
BdkDescriptorPublicKey::MultiXPub(_) => Err(DescriptorKeyError::InvalidKeyType),
}
}

Expand All @@ -242,7 +248,7 @@ impl DescriptorPublicKey {
mod test {
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
// use bdk::bitcoin::hashes::hex::ToHex;
use crate::error::Alpha3Error;
use crate::error::DescriptorKeyError;
use bdk::bitcoin::Network;
use std::sync::Arc;

Expand All @@ -254,31 +260,31 @@ mod test {
fn derive_dsk(
key: &DescriptorSecretKey,
path: &str,
) -> Result<Arc<DescriptorSecretKey>, Alpha3Error> {
) -> Result<Arc<DescriptorSecretKey>, DescriptorKeyError> {
let path = DerivationPath::new(path.to_string()).unwrap();
key.derive(&path)
}

fn extend_dsk(
key: &DescriptorSecretKey,
path: &str,
) -> Result<Arc<DescriptorSecretKey>, Alpha3Error> {
) -> Result<Arc<DescriptorSecretKey>, DescriptorKeyError> {
let path = DerivationPath::new(path.to_string()).unwrap();
key.extend(&path)
}

fn derive_dpk(
key: &DescriptorPublicKey,
path: &str,
) -> Result<Arc<DescriptorPublicKey>, Alpha3Error> {
) -> Result<Arc<DescriptorPublicKey>, DescriptorKeyError> {
let path = DerivationPath::new(path.to_string()).unwrap();
key.derive(&path)
}

fn extend_dpk(
key: &DescriptorPublicKey,
path: &str,
) -> Result<Arc<DescriptorPublicKey>, Alpha3Error> {
) -> Result<Arc<DescriptorPublicKey>, DescriptorKeyError> {
let path = DerivationPath::new(path.to_string()).unwrap();
key.extend(&path)
}
Expand Down
1 change: 1 addition & 0 deletions bdk-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::error::CalculateFeeError;
use crate::error::CannotConnectError;
use crate::error::CreateTxError;
use crate::error::DescriptorError;
use crate::error::DescriptorKeyError;
use crate::error::EsploraError;
use crate::error::ExtractTxError;
use crate::error::FeeRateError;
Expand Down

0 comments on commit e1a9337

Please sign in to comment.