1use core::fmt;
4
5use internals::write_err;
6
7use crate::bip32::Xpub;
8use crate::blockdata::transaction::Transaction;
9use crate::consensus::encode;
10use crate::prelude::*;
11use crate::psbt::raw;
12
13#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
15pub enum PsbtHash {
16 Ripemd,
17 Sha256,
18 Hash160,
19 Hash256,
20}
21#[derive(Debug)]
23#[non_exhaustive]
24pub enum Error {
25 InvalidMagic,
28 MissingUtxo,
30 InvalidSeparator,
32 PsbtUtxoOutOfbounds,
34 InvalidKey(raw::Key),
36 InvalidProprietaryKey,
38 DuplicateKey(raw::Key),
40 UnsignedTxHasScriptSigs,
42 UnsignedTxHasScriptWitnesses,
44 MustHaveUnsignedTx,
46 NoMorePairs,
48 UnexpectedUnsignedTx {
51 expected: Box<Transaction>,
53 actual: Box<Transaction>,
55 },
56 NonStandardSighashType(u32),
58 InvalidHash(hashes::FromSliceError),
60 InvalidPreimageHashPair {
62 hash_type: PsbtHash,
64 preimage: Box<[u8]>,
66 hash: Box<[u8]>,
68 },
69 CombineInconsistentKeySources(Box<Xpub>),
72 ConsensusEncoding(encode::Error),
74 NegativeFee,
76 FeeOverflow,
78 InvalidPublicKey(crate::crypto::key::FromSliceError),
80 InvalidSecp256k1PublicKey(secp256k1::Error),
82 InvalidXOnlyPublicKey,
84 InvalidEcdsaSignature(crate::crypto::ecdsa::Error),
86 InvalidTaprootSignature(crate::crypto::taproot::SigFromSliceError),
88 InvalidControlBlock,
90 InvalidLeafVersion,
92 Taproot(&'static str),
94 TapTree(crate::taproot::IncompleteBuilderError),
96 XPubKey(&'static str),
98 Version(&'static str),
100 PartialDataConsumption,
102 Io(io::Error),
104}
105
106internals::impl_from_infallible!(Error);
107
108impl fmt::Display for Error {
109 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
110 use Error::*;
111
112 match *self {
113 InvalidMagic => f.write_str("invalid magic"),
114 MissingUtxo => f.write_str("UTXO information is not present in PSBT"),
115 InvalidSeparator => f.write_str("invalid separator"),
116 PsbtUtxoOutOfbounds =>
117 f.write_str("output index is out of bounds of non witness script output array"),
118 InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey),
119 InvalidProprietaryKey =>
120 write!(f, "non-proprietary key type found when proprietary key was expected"),
121 DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey),
122 UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"),
123 UnsignedTxHasScriptWitnesses =>
124 f.write_str("the unsigned transaction has script witnesses"),
125 MustHaveUnsignedTx =>
126 f.write_str("partially signed transactions must have an unsigned transaction"),
127 NoMorePairs => f.write_str("no more key-value pairs for this psbt map"),
128 UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(
129 f,
130 "different unsigned transaction: expected {}, actual {}",
131 e.compute_txid(),
132 a.compute_txid()
133 ),
134 NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht),
135 InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e),
136 InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => {
137 write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash)
139 }
140 CombineInconsistentKeySources(ref s) => {
141 write!(f, "combine conflict: {}", s)
142 }
143 ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e),
144 NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"),
145 FeeOverflow => f.write_str("integer overflow in fee calculation"),
146 InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e),
147 InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e),
148 InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"),
149 InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e),
150 InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e),
151 InvalidControlBlock => f.write_str("invalid control block"),
152 InvalidLeafVersion => f.write_str("invalid leaf version"),
153 Taproot(s) => write!(f, "taproot error - {}", s),
154 TapTree(ref e) => write_err!(f, "taproot tree error"; e),
155 XPubKey(s) => write!(f, "xpub key error - {}", s),
156 Version(s) => write!(f, "version error {}", s),
157 PartialDataConsumption =>
158 f.write_str("data not consumed entirely when explicitly deserializing"),
159 Io(ref e) => write_err!(f, "I/O error"; e),
160 }
161 }
162}
163
164#[cfg(feature = "std")]
165impl std::error::Error for Error {
166 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
167 use Error::*;
168
169 match *self {
170 InvalidHash(ref e) => Some(e),
171 ConsensusEncoding(ref e) => Some(e),
172 Io(ref e) => Some(e),
173 InvalidMagic
174 | MissingUtxo
175 | InvalidSeparator
176 | PsbtUtxoOutOfbounds
177 | InvalidKey(_)
178 | InvalidProprietaryKey
179 | DuplicateKey(_)
180 | UnsignedTxHasScriptSigs
181 | UnsignedTxHasScriptWitnesses
182 | MustHaveUnsignedTx
183 | NoMorePairs
184 | UnexpectedUnsignedTx { .. }
185 | NonStandardSighashType(_)
186 | InvalidPreimageHashPair { .. }
187 | CombineInconsistentKeySources(_)
188 | NegativeFee
189 | FeeOverflow
190 | InvalidPublicKey(_)
191 | InvalidSecp256k1PublicKey(_)
192 | InvalidXOnlyPublicKey
193 | InvalidEcdsaSignature(_)
194 | InvalidTaprootSignature(_)
195 | InvalidControlBlock
196 | InvalidLeafVersion
197 | Taproot(_)
198 | TapTree(_)
199 | XPubKey(_)
200 | Version(_)
201 | PartialDataConsumption => None,
202 }
203 }
204}
205
206impl From<hashes::FromSliceError> for Error {
207 fn from(e: hashes::FromSliceError) -> Error { Error::InvalidHash(e) }
208}
209
210impl From<encode::Error> for Error {
211 fn from(e: encode::Error) -> Self { Error::ConsensusEncoding(e) }
212}
213
214impl From<io::Error> for Error {
215 fn from(e: io::Error) -> Self { Error::Io(e) }
216}