feat: add derivation path related error

This commit is contained in:
Matthew 2024-04-18 15:53:05 -05:00
parent 6ac386c8df
commit 0a75fc1279
No known key found for this signature in database
GPG Key ID: 8D4FCD82DD54DDD2
4 changed files with 142 additions and 5 deletions

View File

@ -18,6 +18,21 @@ interface Bip39Error {
AmbiguousLanguages(string languages); AmbiguousLanguages(string languages);
}; };
[Error]
interface Bip32Error {
CannotDeriveFromHardenedKey();
Secp256k1(string e);
InvalidChildNumber(u32 child_number);
InvalidChildNumberFormat();
InvalidDerivationPathFormat();
UnknownVersion(string version);
WrongExtendedKeyLength(u32 length);
Base58(string e);
Hex(string e);
InvalidPublicKeyHexLength(u32 length);
UnknownError(string e);
};
[Error] [Error]
interface CalculateFeeError { interface CalculateFeeError {
MissingTxOut(sequence<OutPoint> out_points); MissingTxOut(sequence<OutPoint> out_points);
@ -335,7 +350,7 @@ interface Mnemonic {
}; };
interface DerivationPath { interface DerivationPath {
[Throws=Alpha3Error] [Throws=Bip32Error]
constructor(string path); constructor(string path);
}; };

View File

@ -13,8 +13,12 @@ use bdk_file_store::FileError as BdkFileError;
use bdk_file_store::IterError; use bdk_file_store::IterError;
use bitcoin_internals::hex::display::DisplayHex; use bitcoin_internals::hex::display::DisplayHex;
use crate::error::bip32::Error as BdkBip32Error;
use bdk::bitcoin::address::ParseError; use bdk::bitcoin::address::ParseError;
use bdk::keys::bip39::Error as BdkBip39Error; use bdk::keys::bip39::Error as BdkBip39Error;
use bdk::bitcoin::bip32;
use std::convert::Infallible; use std::convert::Infallible;
use std::convert::TryInto; use std::convert::TryInto;
@ -24,6 +28,42 @@ pub enum Alpha3Error {
Generic, Generic,
} }
#[derive(Debug, thiserror::Error)]
pub enum Bip32Error {
#[error("Cannot derive from a hardened key")]
CannotDeriveFromHardenedKey,
#[error("Secp256k1 error: {e}")]
Secp256k1 { e: String },
#[error("Invalid child number: {child_number}")]
InvalidChildNumber { child_number: u32 },
#[error("Invalid format for child number")]
InvalidChildNumberFormat,
#[error("Invalid derivation path format")]
InvalidDerivationPathFormat,
#[error("Unknown version: {version}")]
UnknownVersion { version: String },
#[error("Wrong extended key length: {length}")]
WrongExtendedKeyLength { length: u32 },
#[error("Base58 error: {e}")]
Base58 { e: String },
#[error("Hexadecimal conversion error: {e}")]
Hex { e: String },
#[error("Invalid public key hex length: {length}")]
InvalidPublicKeyHexLength { length: u32 },
#[error("Unknown error: {e}")]
UnknownError { e: String },
}
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum CalculateFeeError { pub enum CalculateFeeError {
#[error("missing transaction output: {out_points:?}")] #[error("missing transaction output: {out_points:?}")]
@ -470,6 +510,34 @@ impl From<bdk::bitcoin::bip32::Error> for Alpha3Error {
} }
} }
impl From<BdkBip32Error> for Bip32Error {
fn from(error: BdkBip32Error) -> Self {
match error {
BdkBip32Error::CannotDeriveFromHardenedKey => Bip32Error::CannotDeriveFromHardenedKey,
BdkBip32Error::Secp256k1(err) => Bip32Error::Secp256k1 { e: err.to_string() },
BdkBip32Error::InvalidChildNumber(num) => {
Bip32Error::InvalidChildNumber { child_number: num }
}
BdkBip32Error::InvalidChildNumberFormat => Bip32Error::InvalidChildNumberFormat,
BdkBip32Error::InvalidDerivationPathFormat => Bip32Error::InvalidDerivationPathFormat,
BdkBip32Error::UnknownVersion(bytes) => Bip32Error::UnknownVersion {
version: bytes.to_lower_hex_string(),
},
BdkBip32Error::WrongExtendedKeyLength(len) => {
Bip32Error::WrongExtendedKeyLength { length: len as u32 }
}
BdkBip32Error::Base58(err) => Bip32Error::Base58 { e: err.to_string() },
BdkBip32Error::Hex(err) => Bip32Error::Hex { e: err.to_string() },
BdkBip32Error::InvalidPublicKeyHexLength(len) => {
Bip32Error::InvalidPublicKeyHexLength { length: len as u32 }
}
_ => Bip32Error::UnknownError {
e: format!("Unhandled error: {:?}", error),
},
}
}
}
impl From<NewError<std::io::Error>> for Alpha3Error { impl From<NewError<std::io::Error>> for Alpha3Error {
fn from(_: NewError<std::io::Error>) -> Self { fn from(_: NewError<std::io::Error>) -> Self {
Alpha3Error::Generic Alpha3Error::Generic
@ -622,7 +690,8 @@ impl From<bdk::bitcoin::psbt::ExtractTxError> for ExtractTxError {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::error::{ use crate::error::{
Bip39Error, CannotConnectError, EsploraError, PersistenceError, WalletCreationError, Bip32Error, Bip39Error, CannotConnectError, EsploraError, PersistenceError,
WalletCreationError,
}; };
use crate::CalculateFeeError; use crate::CalculateFeeError;
use crate::OutPoint; use crate::OutPoint;
@ -869,6 +938,58 @@ mod test {
assert_eq!( assert_eq!(
format!("{}", error), format!("{}", error),
"ambiguous languages detected: English, Spanish" "ambiguous languages detected: English, Spanish"
)
}
#[test]
fn test_error_bip32() {
let error = Bip32Error::CannotDeriveFromHardenedKey;
assert_eq!(format!("{}", error), "Cannot derive from a hardened key");
let error = Bip32Error::Secp256k1 {
e: "Secp256k1 failure".to_string(),
};
assert_eq!(format!("{}", error), "Secp256k1 error: Secp256k1 failure");
let error = Bip32Error::InvalidChildNumber { child_number: 42 };
assert_eq!(format!("{}", error), "Invalid child number: 42");
let error = Bip32Error::InvalidChildNumberFormat;
assert_eq!(format!("{}", error), "Invalid format for child number");
let error = Bip32Error::InvalidDerivationPathFormat;
assert_eq!(format!("{}", error), "Invalid derivation path format");
let error = Bip32Error::UnknownVersion {
version: "deadbeef".to_string(),
};
assert_eq!(format!("{}", error), "Unknown version: deadbeef");
let error = Bip32Error::WrongExtendedKeyLength { length: 128 };
assert_eq!(format!("{}", error), "Wrong extended key length: 128");
let error = Bip32Error::Base58 {
e: "Base58 error".to_string(),
};
assert_eq!(format!("{}", error), "Base58 error: Base58 error");
let error = Bip32Error::Hex {
e: "Hex error".to_string(),
};
assert_eq!(
format!("{}", error),
"Hexadecimal conversion error: Hex error"
);
let error = Bip32Error::InvalidPublicKeyHexLength { length: 65 };
assert_eq!(format!("{}", error), "Invalid public key hex length: 65");
let error = Bip32Error::UnknownError {
e: "An unknown error occurred".to_string(),
};
assert_eq!(
format!("{}", error),
"Unknown error: An unknown error occurred"
); );
} }
} }

View File

@ -1,4 +1,4 @@
use crate::error::{Alpha3Error, Bip39Error}; use crate::error::{Alpha3Error, Bip32Error, Bip39Error};
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath; use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::key::Secp256k1; use bdk::bitcoin::key::Secp256k1;
@ -57,12 +57,12 @@ pub(crate) struct DerivationPath {
} }
impl DerivationPath { impl DerivationPath {
pub(crate) fn new(path: String) -> Result<Self, Alpha3Error> { pub(crate) fn new(path: String) -> Result<Self, Bip32Error> {
BdkDerivationPath::from_str(&path) BdkDerivationPath::from_str(&path)
.map(|x| DerivationPath { .map(|x| DerivationPath {
inner_mutex: Mutex::new(x), inner_mutex: Mutex::new(x),
}) })
.map_err(|_| Alpha3Error::Generic) .map_err(Bip32Error::from)
} }
} }

View File

@ -15,6 +15,7 @@ use crate::bitcoin::TxOut;
use crate::descriptor::Descriptor; use crate::descriptor::Descriptor;
use crate::error::AddressError; use crate::error::AddressError;
use crate::error::Alpha3Error; use crate::error::Alpha3Error;
use crate::error::Bip32Error;
use crate::error::Bip39Error; use crate::error::Bip39Error;
use crate::error::CalculateFeeError; use crate::error::CalculateFeeError;
use crate::error::CannotConnectError; use crate::error::CannotConnectError;