use crate::prelude::*;
use core::fmt;
use crate::blockdata::transaction::Transaction;
use crate::consensus::encode;
use crate::util::psbt::raw;
use crate::hashes;
use crate::util::bip32::ExtendedPubKey;
use crate::internal_macros::write_err;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum PsbtHash {
Ripemd,
Sha256,
Hash160,
Hash256,
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[non_exhaustive]
pub enum Error {
InvalidMagic,
MissingUtxo,
InvalidSeparator,
PsbtUtxoOutOfbounds,
InvalidKey(raw::Key),
InvalidProprietaryKey,
DuplicateKey(raw::Key),
UnsignedTxHasScriptSigs,
UnsignedTxHasScriptWitnesses,
MustHaveUnsignedTx,
NoMorePairs,
UnexpectedUnsignedTx {
expected: Box<Transaction>,
actual: Box<Transaction>,
},
NonStandardSighashType(u32),
HashParse(hashes::Error),
InvalidPreimageHashPair {
hash_type: PsbtHash,
preimage: Box<[u8]>,
hash: Box<[u8]>,
},
CombineInconsistentKeySources(Box<ExtendedPubKey>),
ConsensusEncoding,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidMagic => f.write_str("invalid magic"),
Error::MissingUtxo => f.write_str("UTXO information is not present in PSBT"),
Error::InvalidSeparator => f.write_str("invalid separator"),
Error::PsbtUtxoOutOfbounds => f.write_str("output index is out of bounds of non witness script output array"),
Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey),
Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"),
Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey),
Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"),
Error::UnsignedTxHasScriptWitnesses => f.write_str("the unsigned transaction has script witnesses"),
Error::MustHaveUnsignedTx => {
f.write_str("partially signed transactions must have an unsigned transaction")
}
Error::NoMorePairs => f.write_str("no more key-value pairs for this psbt map"),
Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()),
Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht),
Error::HashParse(ref e) => write_err!(f, "hash parse error"; e),
Error::InvalidPreimageHashPair{ref preimage, ref hash, ref hash_type} => {
write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash )
},
Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) },
Error::ConsensusEncoding => f.write_str("bitcoin consensus or BIP-174 encoding error"),
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use self::Error::*;
match self {
HashParse(e) => Some(e),
| InvalidMagic
| MissingUtxo
| InvalidSeparator
| PsbtUtxoOutOfbounds
| InvalidKey(_)
| InvalidProprietaryKey
| DuplicateKey(_)
| UnsignedTxHasScriptSigs
| UnsignedTxHasScriptWitnesses
| MustHaveUnsignedTx
| NoMorePairs
| UnexpectedUnsignedTx { .. }
| NonStandardSighashType(_)
| InvalidPreimageHashPair{ .. }
| CombineInconsistentKeySources(_)
| ConsensusEncoding => None,
}
}
}
#[doc(hidden)]
impl From<hashes::Error> for Error {
fn from(e: hashes::Error) -> Error {
Error::HashParse(e)
}
}
impl From<encode::Error> for Error {
fn from(err: encode::Error) -> Self {
match err {
encode::Error::Psbt(err) => err,
_ => Error::ConsensusEncoding,
}
}
}