feat: add descriptor related errors

This commit is contained in:
thunderbiscuit 2024-04-05 10:53:54 -04:00
parent 0e617bc986
commit 97a104fd5f
No known key found for this signature in database
GPG Key ID: 88253696EB836462
7 changed files with 110 additions and 30 deletions

View File

@ -88,6 +88,22 @@ interface PsbtParseError {
Base64Encoding(string e); Base64Encoding(string e);
}; };
[Error]
interface DescriptorError {
InvalidHdKeyPath();
InvalidDescriptorChecksum();
HardenedDerivationXpub();
MultiPath();
Key(string e);
Policy(string e);
InvalidDescriptorCharacter(string char);
Bip32(string e);
Base58(string e);
Pk(string e);
Miniscript(string e);
Hex(string e);
};
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// bdk crate - types module // bdk crate - types module
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -309,7 +325,7 @@ interface DescriptorPublicKey {
}; };
interface Descriptor { interface Descriptor {
[Throws=Alpha3Error] [Throws=DescriptorError]
constructor(string descriptor, Network network); constructor(string descriptor, Network network);
[Name=new_bip44] [Name=new_bip44]

View File

@ -1,5 +1,4 @@
use crate::error::{PsbtParseError, TransactionError}; use crate::error::{AddressError, PsbtParseError, TransactionError};
use crate::error::AddressError;
use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked}; use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf; use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
@ -198,7 +197,6 @@ impl PartiallySignedTransaction {
pub(crate) fn new(psbt_base64: String) -> Result<Self, PsbtParseError> { pub(crate) fn new(psbt_base64: String) -> Result<Self, PsbtParseError> {
let psbt: BdkPartiallySignedTransaction = let psbt: BdkPartiallySignedTransaction =
BdkPartiallySignedTransaction::from_str(&psbt_base64)?; BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
// .map_err(|_| Alpha3Error::Generic)?;
Ok(PartiallySignedTransaction { Ok(PartiallySignedTransaction {
inner: Mutex::new(psbt), inner: Mutex::new(psbt),

View File

@ -1,4 +1,4 @@
use crate::error::Alpha3Error; use crate::error::DescriptorError;
use crate::keys::DescriptorPublicKey; use crate::keys::DescriptorPublicKey;
use crate::keys::DescriptorSecretKey; use crate::keys::DescriptorSecretKey;
@ -23,7 +23,7 @@ pub struct Descriptor {
} }
impl Descriptor { impl Descriptor {
pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, Alpha3Error> { pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, DescriptorError> {
let secp = Secp256k1::new(); let secp = Secp256k1::new();
let (extended_descriptor, key_map) = descriptor.into_wallet_descriptor(&secp, network)?; let (extended_descriptor, key_map) = descriptor.into_wallet_descriptor(&secp, network)?;
Ok(Self { Ok(Self {
@ -276,8 +276,6 @@ mod test {
use crate::*; use crate::*;
use assert_matches::assert_matches; use assert_matches::assert_matches;
use crate::Alpha3Error;
fn get_descriptor_secret_key() -> DescriptorSecretKey { fn get_descriptor_secret_key() -> DescriptorSecretKey {
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap(); let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
DescriptorSecretKey::new(Network::Testnet, &mnemonic, None) DescriptorSecretKey::new(Network::Testnet, &mnemonic, None)
@ -392,8 +390,8 @@ mod test {
fn test_descriptor_from_string() { fn test_descriptor_from_string() {
let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet); let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet);
let descriptor2 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Bitcoin); let descriptor2 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Bitcoin);
// Creating a Descriptor using an extended key that doesn't match the network provided will throw and InvalidNetwork Error // Creating a Descriptor using an extended key that doesn't match the network provided will throw a DescriptorError::Key with inner InvalidNetwork error
assert!(descriptor1.is_ok()); assert!(descriptor1.is_ok());
assert_matches!(descriptor2.unwrap_err(), Alpha3Error::Generic) assert_matches!(descriptor2.unwrap_err(), DescriptorError::Key { .. });
} }
} }

View File

@ -1,17 +1,17 @@
use crate::bitcoin::OutPoint; use crate::bitcoin::OutPoint;
use bdk::chain::tx_graph::CalculateFeeError as BdkCalculateFeeError;
use bdk_esplora::esplora_client::{Error as BdkEsploraError};
use bdk::bitcoin::psbt::PsbtParseError as BdkPsbtParseError; use bdk::bitcoin::psbt::PsbtParseError as BdkPsbtParseError;
use bdk::bitcoin::Network; use bdk::bitcoin::Network;
use bdk::descriptor::DescriptorError; use bdk::chain::tx_graph::CalculateFeeError as BdkCalculateFeeError;
use bdk::descriptor::DescriptorError as BdkDescriptorError;
use bdk::wallet::error::{BuildFeeBumpError, CreateTxError}; use bdk::wallet::error::{BuildFeeBumpError, CreateTxError};
use bdk::wallet::tx_builder::{AddUtxoError, AllowShrinkingError}; use bdk::wallet::tx_builder::{AddUtxoError, AllowShrinkingError};
use bdk::wallet::{NewError, NewOrLoadError}; use bdk::wallet::{NewError, NewOrLoadError};
use bdk_esplora::esplora_client::Error as BdkEsploraError;
use bdk_file_store::FileError as BdkFileError; 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 std::convert::Infallible; use std::convert::Infallible;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
@ -204,6 +204,70 @@ pub enum PsbtParseError {
Base64Encoding { e: String }, Base64Encoding { e: String },
} }
#[derive(Debug, thiserror::Error)]
pub enum DescriptorError {
#[error("invalid hd key path")]
InvalidHdKeyPath,
#[error("the provided descriptor doesn't match its checksum")]
InvalidDescriptorChecksum,
#[error("the descriptor contains hardened derivation steps on public extended keys")]
HardenedDerivationXpub,
#[error("the descriptor contains multipath keys, which are not supported yet")]
MultiPath,
#[error("key error: {e}")]
Key { e: String },
#[error("policy error: {e}")]
Policy { e: String },
#[error("invalid descriptor character: {char}")]
InvalidDescriptorCharacter { char: String },
#[error("BIP32 error: {e}")]
Bip32 { e: String },
#[error("Base58 error: {e}")]
Base58 { e: String },
#[error("Key-related error: {e}")]
Pk { e: String },
#[error("Miniscript error: {e}")]
Miniscript { e: String },
#[error("Hex decoding error: {e}")]
Hex { e: String },
}
impl From<BdkDescriptorError> for DescriptorError {
fn from(error: BdkDescriptorError) -> Self {
match error {
BdkDescriptorError::InvalidHdKeyPath => DescriptorError::InvalidHdKeyPath,
BdkDescriptorError::InvalidDescriptorChecksum => {
DescriptorError::InvalidDescriptorChecksum
}
BdkDescriptorError::HardenedDerivationXpub => DescriptorError::HardenedDerivationXpub,
BdkDescriptorError::MultiPath => DescriptorError::MultiPath,
BdkDescriptorError::Key(e) => DescriptorError::Key { e: e.to_string() },
BdkDescriptorError::Policy(e) => DescriptorError::Policy { e: e.to_string() },
BdkDescriptorError::InvalidDescriptorCharacter(char) => {
DescriptorError::InvalidDescriptorCharacter {
char: char.to_string(),
}
}
BdkDescriptorError::Bip32(e) => DescriptorError::Bip32 { e: e.to_string() },
BdkDescriptorError::Base58(e) => DescriptorError::Base58 { e: e.to_string() },
BdkDescriptorError::Pk(e) => DescriptorError::Pk { e: e.to_string() },
BdkDescriptorError::Miniscript(e) => DescriptorError::Miniscript { e: e.to_string() },
BdkDescriptorError::Hex(e) => DescriptorError::Hex { e: e.to_string() },
}
}
}
impl From<BdkPsbtParseError> for PsbtParseError { impl From<BdkPsbtParseError> for PsbtParseError {
fn from(error: BdkPsbtParseError) -> Self { fn from(error: BdkPsbtParseError) -> Self {
match error { match error {
@ -254,11 +318,11 @@ impl From<std::io::Error> for PersistenceError {
} }
} }
impl From<DescriptorError> for Alpha3Error { // impl From<DescriptorError> for Alpha3Error {
fn from(_: DescriptorError) -> Self { // fn from(_: DescriptorError) -> Self {
Alpha3Error::Generic // Alpha3Error::Generic
} // }
} // }
impl From<AllowShrinkingError> for Alpha3Error { impl From<AllowShrinkingError> for Alpha3Error {
fn from(_: AllowShrinkingError) -> Self { fn from(_: AllowShrinkingError) -> Self {
@ -364,10 +428,14 @@ impl From<bdk::bitcoin::address::Error> for AddressError {
AddressError::MalformedWitnessVersion AddressError::MalformedWitnessVersion
} }
bdk::bitcoin::address::Error::InvalidWitnessProgramLength(length) => { bdk::bitcoin::address::Error::InvalidWitnessProgramLength(length) => {
AddressError::InvalidWitnessProgramLength { length: length as u64 } AddressError::InvalidWitnessProgramLength {
length: length as u64,
}
} }
bdk::bitcoin::address::Error::InvalidSegwitV0ProgramLength(length) => { bdk::bitcoin::address::Error::InvalidSegwitV0ProgramLength(length) => {
AddressError::InvalidSegwitV0ProgramLength { length: length as u64 } AddressError::InvalidSegwitV0ProgramLength {
length: length as u64,
}
} }
bdk::bitcoin::address::Error::UncompressedPubkey => AddressError::UncompressedPubkey, bdk::bitcoin::address::Error::UncompressedPubkey => AddressError::UncompressedPubkey,
bdk::bitcoin::address::Error::ExcessiveScriptSize => AddressError::ExcessiveScriptSize, bdk::bitcoin::address::Error::ExcessiveScriptSize => AddressError::ExcessiveScriptSize,
@ -379,13 +447,11 @@ impl From<bdk::bitcoin::address::Error> for AddressError {
required, required,
found, found,
address, address,
} => { } => AddressError::NetworkValidation {
AddressError::NetworkValidation {
required, required,
found, found,
address: format!("{:?}", address), address: format!("{:?}", address),
} },
}
_ => AddressError::OtherAddressError, _ => AddressError::OtherAddressError,
} }
} }

View File

@ -1,12 +1,12 @@
use crate::error::{Alpha3Error, EsploraError}; use crate::error::{Alpha3Error, EsploraError};
use crate::wallet::{Update, Wallet}; use crate::wallet::{Update, Wallet};
use crate::bitcoin::Transaction;
use bdk::bitcoin::Transaction as BdkTransaction; use bdk::bitcoin::Transaction as BdkTransaction;
use bdk::wallet::Update as BdkUpdate; use bdk::wallet::Update as BdkUpdate;
use bdk_esplora::esplora_client::{BlockingClient, Builder}; use bdk_esplora::esplora_client::{BlockingClient, Builder};
use bdk_esplora::EsploraExt; use bdk_esplora::EsploraExt;
use crate::bitcoin::Transaction;
use std::sync::Arc; use std::sync::Arc;
pub struct EsploraClient(BlockingClient); pub struct EsploraClient(BlockingClient);

View File

@ -16,6 +16,7 @@ use crate::descriptor::Descriptor;
use crate::error::AddressError; use crate::error::AddressError;
use crate::error::Alpha3Error; use crate::error::Alpha3Error;
use crate::error::CalculateFeeError; use crate::error::CalculateFeeError;
use crate::error::DescriptorError;
use crate::error::EsploraError; use crate::error::EsploraError;
use crate::error::FeeRateError; use crate::error::FeeRateError;
use crate::error::PersistenceError; use crate::error::PersistenceError;

View File

@ -1,6 +1,7 @@
use crate::bitcoin::{Address, OutPoint, Script, Transaction, TxOut};
use crate::error::FeeRateError; use crate::error::FeeRateError;
use crate::bitcoin::{Address, OutPoint, Script, Transaction, TxOut};
use bdk::bitcoin::FeeRate as BdkFeeRate; use bdk::bitcoin::FeeRate as BdkFeeRate;
use bdk::bitcoin::Transaction as BdkTransaction; use bdk::bitcoin::Transaction as BdkTransaction;
use bdk::chain::tx_graph::CanonicalTx as BdkCanonicalTx; use bdk::chain::tx_graph::CanonicalTx as BdkCanonicalTx;