feat: add address related errors

This commit is contained in:
thunderbiscuit 2024-04-04 12:03:12 -04:00
parent ab87355f9d
commit 84f2497aeb
No known key found for this signature in database
GPG Key ID: 88253696EB836462
4 changed files with 134 additions and 9 deletions

View File

@ -52,6 +52,25 @@ enum FeeRateError {
"ArithmeticOverflow" "ArithmeticOverflow"
}; };
[Error]
interface AddressError {
Base58();
Bech32();
EmptyBech32Payload();
InvalidBech32Variant();
InvalidWitnessVersion(u8 version);
UnparsableWitnessVersion();
MalformedWitnessVersion();
InvalidWitnessProgramLength(u64 length);
InvalidSegwitV0ProgramLength(u64 length);
UncompressedPubkey();
ExcessiveScriptSize();
UnrecognizedScript();
UnknownAddressType(string s);
NetworkValidation(Network required, Network found, string address);
OtherAddressError();
};
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// bdk crate - types module // bdk crate - types module
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -360,7 +379,7 @@ enum WordCount {
}; };
interface Address { interface Address {
[Throws=Alpha3Error] [Throws=AddressError]
constructor(string address, Network network); constructor(string address, Network network);
Network network(); Network network();

View File

@ -41,14 +41,9 @@ pub struct Address {
} }
impl Address { impl Address {
pub fn new(address: String, network: Network) -> Result<Self, Alpha3Error> { pub fn new(address: String, network: Network) -> Result<Self, AddressError> {
let parsed_address = address let parsed_address = address.parse::<bdk::bitcoin::Address<NetworkUnchecked>>()?;
.parse::<bdk::bitcoin::Address<NetworkUnchecked>>() let network_checked_address = parsed_address.require_network(network)?;
.map_err(|_| Alpha3Error::Generic)?;
let network_checked_address = parsed_address
.require_network(network)
.map_err(|_| Alpha3Error::Generic)?;
Ok(Address { Ok(Address {
inner: network_checked_address, inner: network_checked_address,

View File

@ -107,6 +107,66 @@ pub enum FeeRateError {
ArithmeticOverflow, ArithmeticOverflow,
} }
#[derive(Debug, thiserror::Error)]
pub enum AddressError {
#[error("base58 address encoding error")]
Base58,
#[error("bech32 address encoding error")]
Bech32,
#[error("the bech32 payload was empty")]
EmptyBech32Payload,
#[error("invalid bech32 checksum variant found")]
InvalidBech32Variant,
#[error("invalid witness script version: {version}")]
InvalidWitnessVersion { version: u8 },
#[error("incorrect format of a witness version byte")]
UnparsableWitnessVersion,
#[error(
"bitcoin script opcode does not match any known witness version, the script is malformed"
)]
MalformedWitnessVersion,
#[error("the witness program must be between 2 and 40 bytes in length: length={length}")]
InvalidWitnessProgramLength { length: u64 },
#[error("a v0 witness program must be either of length 20 or 32 bytes: length={length}")]
InvalidSegwitV0ProgramLength { length: u64 },
#[error("an uncompressed pubkey was used where it is not allowed")]
UncompressedPubkey,
#[error("script size exceed 520 bytes")]
ExcessiveScriptSize,
#[error("script is not p2pkh, p2sh, or witness program")]
UnrecognizedScript,
#[error("unknown address type: '{s}' is either invalid or not supported")]
UnknownAddressType { s: String },
#[error(
"address {address} belongs to network {found} which is different from required {required}"
)]
NetworkValidation {
/// Network that was required.
required: Network,
/// Network on which the address was found to be valid.
found: Network,
/// The address itself
address: String,
},
// This is required because the bdk::bitcoin::address::Error is non-exhaustive
#[error("other address error")]
OtherAddressError,
}
impl From<BdkFileError> for WalletCreationError { impl From<BdkFileError> for WalletCreationError {
fn from(error: BdkFileError) -> Self { fn from(error: BdkFileError) -> Self {
match error { match error {
@ -234,6 +294,56 @@ impl From<BdkEsploraError> for EsploraError {
} }
} }
impl From<bdk::bitcoin::address::Error> for AddressError {
fn from(error: bdk::bitcoin::address::Error) -> Self {
match error {
bdk::bitcoin::address::Error::Base58(_) => AddressError::Base58,
bdk::bitcoin::address::Error::Bech32(_) => AddressError::Bech32,
bdk::bitcoin::address::Error::EmptyBech32Payload => AddressError::EmptyBech32Payload,
bdk::bitcoin::address::Error::InvalidBech32Variant { .. } => {
AddressError::InvalidBech32Variant
}
bdk::bitcoin::address::Error::InvalidWitnessVersion(version) => {
AddressError::InvalidWitnessVersion { version }
}
bdk::bitcoin::address::Error::UnparsableWitnessVersion(_) => {
AddressError::UnparsableWitnessVersion
}
bdk::bitcoin::address::Error::MalformedWitnessVersion => {
AddressError::MalformedWitnessVersion
}
bdk::bitcoin::address::Error::InvalidWitnessProgramLength(length) => {
let length = length as u64;
AddressError::InvalidWitnessProgramLength { length }
}
bdk::bitcoin::address::Error::InvalidSegwitV0ProgramLength(length) => {
let length = length as u64;
AddressError::InvalidSegwitV0ProgramLength { length }
}
bdk::bitcoin::address::Error::UncompressedPubkey => AddressError::UncompressedPubkey,
bdk::bitcoin::address::Error::ExcessiveScriptSize => AddressError::ExcessiveScriptSize,
bdk::bitcoin::address::Error::UnrecognizedScript => AddressError::UnrecognizedScript,
bdk::bitcoin::address::Error::UnknownAddressType(s) => {
AddressError::UnknownAddressType { s }
}
bdk::bitcoin::address::Error::NetworkValidation {
required,
found,
address,
} => {
// let address = address.to_string();
let address = format!("{:?}", address);
AddressError::NetworkValidation {
required,
found,
address,
}
}
_ => AddressError::OtherAddressError,
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::error::{EsploraError, PersistenceError, WalletCreationError}; use crate::error::{EsploraError, PersistenceError, WalletCreationError};

View File

@ -13,6 +13,7 @@ use crate::bitcoin::Script;
use crate::bitcoin::Transaction; use crate::bitcoin::Transaction;
use crate::bitcoin::TxOut; use crate::bitcoin::TxOut;
use crate::descriptor::Descriptor; use crate::descriptor::Descriptor;
use crate::error::AddressError;
use crate::error::Alpha3Error; use crate::error::Alpha3Error;
use crate::error::CalculateFeeError; use crate::error::CalculateFeeError;
use crate::error::EsploraError; use crate::error::EsploraError;